Browse Source

Bugfixes on back reference handling for singleRef solves #154

Yann Weber 8 years ago
parent
commit
0b60a24582

+ 1
- 68
lodel/leapi/datahandlers/base_classes.py View File

351
 class SingleRef(Reference):
351
 class SingleRef(Reference):
352
     
352
     
353
     def __init__(self, allowed_classes = None, **kwargs):
353
     def __init__(self, allowed_classes = None, **kwargs):
354
-        super().__init__(allowed_classes = allowed_classes)
354
+        super().__init__(allowed_classes = allowed_classes, **kwargs)
355
  
355
  
356
     ##@brief Check and cast value in appropriate type
356
     ##@brief Check and cast value in appropriate type
357
     #@param value: *
357
     #@param value: *
364
         #    raise FieldValidationError("List or string expected for a set field")
364
         #    raise FieldValidationError("List or string expected for a set field")
365
         return value
365
         return value
366
 
366
 
367
-
368
-
369
 ##@brief This class represent a data_handler for multiple references to another object
367
 ##@brief This class represent a data_handler for multiple references to another object
370
 #@ingroup lodel2_datahandlers
368
 #@ingroup lodel2_datahandlers
371
 #
369
 #
408
         if len(error_list) > 0:
406
         if len(error_list) > 0:
409
             raise FieldValidationError("MultipleRef have for invalid values [%s]  :" % (",".join(error_list)))
407
             raise FieldValidationError("MultipleRef have for invalid values [%s]  :" % (",".join(error_list)))
410
         return new_val
408
         return new_val
411
-    
412
-    ##@brief Construct a multiple ref data
413
-    def construct_data(self, emcomponent, fname, datas, cur_value):
414
-        cur_value = super().construct_data(emcomponent, fname, datas, cur_value)
415
-        if cur_value is not None:
416
-            if self.back_reference is not None:
417
-                br_class = self.back_reference[0]
418
-                for br_id in cur_value:
419
-                    query_filters = list()
420
-                    query_filters.append((br_class.uid_fieldname()[0], '=', br_id))
421
-                    br_obj = br_class.get(query_filters)
422
-                    if len(br_obj) != 0:
423
-                        br_list = br_obj[0].data(self.back_reference[1])
424
-                        if br_list is None:
425
-                            br_list = list()
426
-                        if br_id not in br_list:
427
-                            br_list.append(br_id)
428
-        return cur_value
429
-    
430
-    ## @brief Checks the backreference, updates it if it is not complete
431
-    # @param emcomponent EmComponent : An EmComponent child class instance
432
-    # @param fname : the field name
433
-    # @param datas dict : dict storing fields values
434
-    # @note Not done in case of delete
435
-    def make_consistency(self, emcomponent, fname, datas, type_query):
436
 
409
 
437
-        dh = emcomponent.field(fname)
438
 
410
 
439
-        logger.info('Warning : multiple uid capabilities are broken here')
440
-        uid = datas[emcomponent.uid_fieldname()[0]]
441
-        if self.back_reference is not None:
442
-            target_class = self.back_reference[0]
443
-            target_field = self.back_reference[1]
444
-            target_uidfield = target_class.uid_fieldname()[0]
445
-            l_value = datas[fname]
446
-
447
-            if l_value is not None:
448
-                for value in l_value:
449
-                    query_filters = list()
450
-                    query_filters.append((target_uidfield , '=', value))
451
-                    obj = target_class.get(query_filters)
452
-                    if len(obj) == 0:
453
-                        logger.warning('Object referenced does not exist')
454
-                        return False
455
-                    l_uids_ref = obj[0].data(target_field)
456
-                    if l_uids_ref is None:
457
-                        l_uids_ref = list()
458
-                    if uid not in l_uids_ref:
459
-                        l_uids_ref.append(uid)
460
-                        obj[0].set_data(target_field, l_uids_ref)
461
-                        obj[0].update()
462
-           
463
-            if type_query == 'update':
464
-                query_filters = list()
465
-                query_filters.append((uid, ' in ', target_field))
466
-                objects = target_class.get(query_filters)
467
-                if l_value is None:
468
-                    l_value = list()
469
-                if len(objects) != len(l_value):
470
-                    for obj in objects:
471
-                        l_uids_ref = obj.data(target_field)
472
-                        if obj.data(target_uidfield) not in l_value:
473
-                            l_uids_ref.remove(uid)
474
-                            obj.set_data(target_field, l_uids_ref)
475
-                            obj.update()
476
-
477
-                
478
 ## @brief Class designed to handle datas access will fieldtypes are constructing datas
411
 ## @brief Class designed to handle datas access will fieldtypes are constructing datas
479
 #@ingroup lodel2_datahandlers
412
 #@ingroup lodel2_datahandlers
480
 #
413
 #

+ 32
- 15
plugins/mongodb_datasource/datasource.py View File

104
     def select(self, target, field_list, filters = None, 
104
     def select(self, target, field_list, filters = None, 
105
             relational_filters=None, order=None, group=None, limit=None, 
105
             relational_filters=None, order=None, group=None, limit=None, 
106
             offset=0):
106
             offset=0):
107
-        logger.debug("Select %s on %s filtered by %s and %s " % (
108
-            field_list, target, filters, relational_filters))
109
         if target.is_abstract():
107
         if target.is_abstract():
110
             #Reccursiv calls for abstract LeObject child
108
             #Reccursiv calls for abstract LeObject child
111
             results =  self.__act_on_abstract(target, filters,
109
             results =  self.__act_on_abstract(target, filters,
223
     #@return int : Number of updated records
221
     #@return int : Number of updated records
224
     def update(self, target, filters, relational_filters, upd_datas):
222
     def update(self, target, filters, relational_filters, upd_datas):
225
         self._data_cast(upd_datas)
223
         self._data_cast(upd_datas)
224
+        #fetching current datas state
225
+        mongo_filters = self.__process_filters(
226
+            target, filters, relational_filters)
227
+        old_datas_l = self.__collection(target).find(
228
+            mongo_filters)
229
+        old_datas_l = list(old_datas_l)
230
+        #Running update
226
         res = self.__update_no_backref(target, filters, relational_filters,
231
         res = self.__update_no_backref(target, filters, relational_filters,
227
             upd_datas)
232
             upd_datas)
233
+        #updating backref
228
         self.__update_backref_filtered(target, filters, relational_filters,
234
         self.__update_backref_filtered(target, filters, relational_filters,
229
-            upd_datas)
235
+            upd_datas, old_datas_l)
230
         return res
236
         return res
231
     
237
     
232
     ##@brief Designed to be called by backref update in order to avoid
238
     ##@brief Designed to be called by backref update in order to avoid
243
         #Non abstract beahavior
249
         #Non abstract beahavior
244
         mongo_filters = self.__process_filters(
250
         mongo_filters = self.__process_filters(
245
             target, filters, relational_filters)
251
             target, filters, relational_filters)
252
+        self._data_cast(upd_datas)
246
         mongo_arg = {'$set': upd_datas }
253
         mongo_arg = {'$set': upd_datas }
247
         res = self.__collection(target).update(mongo_filters, mongo_arg)
254
         res = self.__collection(target).update(mongo_filters, mongo_arg)
248
         return res['n']
255
         return res['n']
281
     #@param filters
288
     #@param filters
282
     #@param relational_filters,
289
     #@param relational_filters,
283
     #@param new_datas None | dict : optional new datas if None mean we are deleting
290
     #@param new_datas None | dict : optional new datas if None mean we are deleting
291
+    #@param old_datas_l None | list : if None fetch old datas from db (usefull
292
+    #when modifications are made on instance before updating backrefs)
284
     #@return nothing (for the moment
293
     #@return nothing (for the moment
285
     def __update_backref_filtered(self, target,
294
     def __update_backref_filtered(self, target,
286
-            filters, relational_filters, new_datas = None):
295
+            filters, relational_filters, new_datas = None, old_datas_l = None):
287
         #Getting all the UID of the object that will be deleted in order
296
         #Getting all the UID of the object that will be deleted in order
288
         #to update back_references
297
         #to update back_references
289
-        mongo_filters = self.__process_filters(
290
-            target, filters, relational_filters)
291
-        old_datas_l = self.__collection(target).find(
292
-            mongo_filters)
293
-        old_datas_l = list(old_datas_l)
298
+        if old_datas_l is None:
299
+            mongo_filters = self.__process_filters(
300
+                target, filters, relational_filters)
301
+            old_datas_l = self.__collection(target).find(
302
+                mongo_filters)
303
+            old_datas_l = list(old_datas_l)
304
+            
294
         uidname = target.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
305
         uidname = target.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
295
         for old_datas in old_datas_l:
306
         for old_datas in old_datas_l:
296
             self.__update_backref(
307
             self.__update_backref(
342
         upd_dict = {}
353
         upd_dict = {}
343
         for fname, fdh in target.reference_handlers().items():
354
         for fname, fdh in target.reference_handlers().items():
344
             oldd = old_datas is not None and fname in old_datas and \
355
             oldd = old_datas is not None and fname in old_datas and \
345
-                hasattr(fdh, 'default') and old_datas[fname] != fdh.default
356
+                (not hasattr(fdh, 'default') or old_datas[fname] != fdh.default) \
357
+                and not old_datas[fname] is None
346
             newd = new_datas is not None and fname in new_datas and \
358
             newd = new_datas is not None and fname in new_datas and \
347
-                hasattr(fdh, 'default') and new_datas[fname] != fdh.default
359
+                (not hasattr(fdh, 'default') or new_datas[fname] != fdh.default) \
360
+                and not new_datas[fname] is None
348
             if (oldd and newd and old_datas[fname] == new_datas[fname])\
361
             if (oldd and newd and old_datas[fname] == new_datas[fname])\
349
                     or not(oldd or newd):
362
                     or not(oldd or newd):
350
                 #No changes or not concerned
363
                 #No changes or not concerned
398
                 #value
411
                 #value
399
                 vdict = {}
412
                 vdict = {}
400
                 if oldd:
413
                 if oldd:
401
-                    vdict['old'] = new_datas[fname]
414
+                    vdict['old'] = old_datas[fname]
402
                     uid_val = vdict['old']
415
                     uid_val = vdict['old']
403
                 if newd:
416
                 if newd:
404
                     vdict['new'] = new_datas[fname]
417
                     vdict['new'] = new_datas[fname]
412
                     upd_dict, bref_infos, bref_fname, uid_val)
425
                     upd_dict, bref_infos, bref_fname, uid_val)
413
                 #forging update bref_infos
426
                 #forging update bref_infos
414
                 bref_cls, bref_leo, bref_dh, bref_value = bref_infos
427
                 bref_cls, bref_leo, bref_dh, bref_value = bref_infos
415
-                bref_infos = tuple(bref_cls, bref_leo, bref_dh,
428
+                bref_infos = (bref_cls, bref_leo, bref_dh,
416
                         upd_dict[bref_cls][uid_val][1][bref_fname])
429
                         upd_dict[bref_cls][uid_val][1][bref_fname])
417
                 #fetche and store updated value
430
                 #fetche and store updated value
418
                 new_bref_val = self.__back_ref_upd_one_value(
431
                 new_bref_val = self.__back_ref_upd_one_value(
419
-                    fname, fdh, tuid, **vdict)
432
+                    fname, fdh, tuid, bref_infos, **vdict)
420
                 upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
433
                 upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
421
         #Now we've got our upd_dict ready.
434
         #Now we've got our upd_dict ready.
422
         #running the updates
435
         #running the updates
478
                     raise MongoDbConsistencyError("The value we want to \
491
                     raise MongoDbConsistencyError("The value we want to \
479
 delete in this back reference update was not found in the back referenced \
492
 delete in this back reference update was not found in the back referenced \
480
 object : %s. Value was : '%s'" % (bref_leo, tuid))
493
 object : %s. Value was : '%s'" % (bref_leo, tuid))
494
+                if isinstance(bref_val, tuple):
495
+                    bref_val = set(bref_val)
481
                 if isinstance(bref_val, set):
496
                 if isinstance(bref_val, set):
482
                     bref_val -= set([tuid])
497
                     bref_val -= set([tuid])
483
                 else:
498
                 else:
487
                     raise MongoDbConsistencyError("The value we want to \
502
                     raise MongoDbConsistencyError("The value we want to \
488
 add in this back reference update was found in the back referenced \
503
 add in this back reference update was found in the back referenced \
489
 object : %s. Value was : '%s'" % (bref_leo, tuid))
504
 object : %s. Value was : '%s'" % (bref_leo, tuid))
505
+                if isinstance(bref_val, tuple):
506
+                    bref_val = set(bref_val)
490
                 if isinstance(bref_val, set):
507
                 if isinstance(bref_val, set):
491
                     bref_val |= set([tuid])
508
                     bref_val |= set([tuid])
492
                 else:
509
                 else:
504
                 if not hasattr(bref_dh, "default"): 
521
                 if not hasattr(bref_dh, "default"): 
505
                     raise MongoDbConsistencyError("Unable to delete a \
522
                     raise MongoDbConsistencyError("Unable to delete a \
506
 value for a back reference update. The concerned field don't have a default \
523
 value for a back reference update. The concerned field don't have a default \
507
-value : in %s field %s" % (bref_leo, bref_fname))
524
+value : in %s field %s" % (bref_leo,fname))
508
                 bref_val = getattr(bref_dh, "default")
525
                 bref_val = getattr(bref_dh, "default")
509
             elif not oldd and newdd:
526
             elif not oldd and newdd:
510
                 bref_val = tuid
527
                 bref_val = tuid

+ 3
- 5
plugins/webui/interface/controllers/admin.py View File

68
                     value=[spl for spl in [
68
                     value=[spl for spl in [
69
                            v.strip() for v in value.split(LIST_SEPARATOR)]
69
                            v.strip() for v in value.split(LIST_SEPARATOR)]
70
                         if len(spl) > 0]
70
                         if len(spl) > 0]
71
+                elif len(value.strip()) == 0:
72
+                    value = None
71
                 try:
73
                 try:
72
                     leo_to_update.set_data(fieldname, value)
74
                     leo_to_update.set_data(fieldname, value)
73
                 except Exception as e:
75
                 except Exception as e:
80
                     fname, error)
82
                     fname, error)
81
             custom_msg += '</ul>'
83
             custom_msg += '</ul>'
82
             raise HttpException(400, custom = custom_msg)
84
             raise HttpException(400, custom = custom_msg)
83
-        try:
84
-            leo_to_update.update()
85
-        except Exception as e:
86
-            raise HttpException(
87
-                500, custom = "Something goes wrong during update : %s" % e)
85
+        leo_to_update.update()
88
 
86
 
89
     # Display of the form with the object's values to be updated
87
     # Display of the form with the object's values to be updated
90
     if 'classname' in request.GET:
88
     if 'classname' in request.GET:

Loading…
Cancel
Save