Browse Source

Bugfixes on back reference handling for singleRef solves #154

Yann Weber 7 years ago
parent
commit
0b60a24582

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

@@ -351,7 +351,7 @@ class Reference(DataHandler):
351 351
 class SingleRef(Reference):
352 352
     
353 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 356
     ##@brief Check and cast value in appropriate type
357 357
     #@param value: *
@@ -364,8 +364,6 @@ class SingleRef(Reference):
364 364
         #    raise FieldValidationError("List or string expected for a set field")
365 365
         return value
366 366
 
367
-
368
-
369 367
 ##@brief This class represent a data_handler for multiple references to another object
370 368
 #@ingroup lodel2_datahandlers
371 369
 #
@@ -408,73 +406,8 @@ class MultipleRef(Reference):
408 406
         if len(error_list) > 0:
409 407
             raise FieldValidationError("MultipleRef have for invalid values [%s]  :" % (",".join(error_list)))
410 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 411
 ## @brief Class designed to handle datas access will fieldtypes are constructing datas
479 412
 #@ingroup lodel2_datahandlers
480 413
 #

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

@@ -104,8 +104,6 @@ class MongoDbDatasource(AbstractDatasource):
104 104
     def select(self, target, field_list, filters = None, 
105 105
             relational_filters=None, order=None, group=None, limit=None, 
106 106
             offset=0):
107
-        logger.debug("Select %s on %s filtered by %s and %s " % (
108
-            field_list, target, filters, relational_filters))
109 107
         if target.is_abstract():
110 108
             #Reccursiv calls for abstract LeObject child
111 109
             results =  self.__act_on_abstract(target, filters,
@@ -223,10 +221,18 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
223 221
     #@return int : Number of updated records
224 222
     def update(self, target, filters, relational_filters, upd_datas):
225 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 231
         res = self.__update_no_backref(target, filters, relational_filters,
227 232
             upd_datas)
233
+        #updating backref
228 234
         self.__update_backref_filtered(target, filters, relational_filters,
229
-            upd_datas)
235
+            upd_datas, old_datas_l)
230 236
         return res
231 237
     
232 238
     ##@brief Designed to be called by backref update in order to avoid
@@ -243,6 +249,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
243 249
         #Non abstract beahavior
244 250
         mongo_filters = self.__process_filters(
245 251
             target, filters, relational_filters)
252
+        self._data_cast(upd_datas)
246 253
         mongo_arg = {'$set': upd_datas }
247 254
         res = self.__collection(target).update(mongo_filters, mongo_arg)
248 255
         return res['n']
@@ -281,16 +288,20 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
281 288
     #@param filters
282 289
     #@param relational_filters,
283 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 293
     #@return nothing (for the moment
285 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 296
         #Getting all the UID of the object that will be deleted in order
288 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 305
         uidname = target.uid_fieldname()[0] #MULTIPLE UID BROKEN HERE
295 306
         for old_datas in old_datas_l:
296 307
             self.__update_backref(
@@ -342,9 +353,11 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
342 353
         upd_dict = {}
343 354
         for fname, fdh in target.reference_handlers().items():
344 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 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 361
             if (oldd and newd and old_datas[fname] == new_datas[fname])\
349 362
                     or not(oldd or newd):
350 363
                 #No changes or not concerned
@@ -398,7 +411,7 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
398 411
                 #value
399 412
                 vdict = {}
400 413
                 if oldd:
401
-                    vdict['old'] = new_datas[fname]
414
+                    vdict['old'] = old_datas[fname]
402 415
                     uid_val = vdict['old']
403 416
                 if newd:
404 417
                     vdict['new'] = new_datas[fname]
@@ -412,11 +425,11 @@ abstract, preparing reccursiv calls" % (target, filters, relational_filters))
412 425
                     upd_dict, bref_infos, bref_fname, uid_val)
413 426
                 #forging update bref_infos
414 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 429
                         upd_dict[bref_cls][uid_val][1][bref_fname])
417 430
                 #fetche and store updated value
418 431
                 new_bref_val = self.__back_ref_upd_one_value(
419
-                    fname, fdh, tuid, **vdict)
432
+                    fname, fdh, tuid, bref_infos, **vdict)
420 433
                 upd_dict[bref_cls][uid_val][1][bref_fname] = new_bref_val
421 434
         #Now we've got our upd_dict ready.
422 435
         #running the updates
@@ -478,6 +491,8 @@ object : %s. Value was : '%s'" % (bref_leo, tuid))
478 491
                     raise MongoDbConsistencyError("The value we want to \
479 492
 delete in this back reference update was not found in the back referenced \
480 493
 object : %s. Value was : '%s'" % (bref_leo, tuid))
494
+                if isinstance(bref_val, tuple):
495
+                    bref_val = set(bref_val)
481 496
                 if isinstance(bref_val, set):
482 497
                     bref_val -= set([tuid])
483 498
                 else:
@@ -487,6 +502,8 @@ object : %s. Value was : '%s'" % (bref_leo, tuid))
487 502
                     raise MongoDbConsistencyError("The value we want to \
488 503
 add in this back reference update was found in the back referenced \
489 504
 object : %s. Value was : '%s'" % (bref_leo, tuid))
505
+                if isinstance(bref_val, tuple):
506
+                    bref_val = set(bref_val)
490 507
                 if isinstance(bref_val, set):
491 508
                     bref_val |= set([tuid])
492 509
                 else:
@@ -504,7 +521,7 @@ have expected value. Expected was %s but found %s in %s" % (
504 521
                 if not hasattr(bref_dh, "default"): 
505 522
                     raise MongoDbConsistencyError("Unable to delete a \
506 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 525
                 bref_val = getattr(bref_dh, "default")
509 526
             elif not oldd and newdd:
510 527
                 bref_val = tuid

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

@@ -68,6 +68,8 @@ def admin_update(request):
68 68
                     value=[spl for spl in [
69 69
                            v.strip() for v in value.split(LIST_SEPARATOR)]
70 70
                         if len(spl) > 0]
71
+                elif len(value.strip()) == 0:
72
+                    value = None
71 73
                 try:
72 74
                     leo_to_update.set_data(fieldname, value)
73 75
                 except Exception as e:
@@ -80,11 +82,7 @@ def admin_update(request):
80 82
                     fname, error)
81 83
             custom_msg += '</ul>'
82 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 87
     # Display of the form with the object's values to be updated
90 88
     if 'classname' in request.GET:

Loading…
Cancel
Save