@@ -453,14 +453,21 @@ class Meta:
453453 models .Index (fields = ["profile" , "model_name" , "partition" , "dirty_bit" ], condition = models .Q (dirty_bit = True ), name = "idx_morango_deserialize" ),
454454 ]
455455
456- def _deserialize_store_model (self , fk_cache , defer_fks = False ): # noqa: C901
456+ def _deserialize_store_model (self , fk_cache , defer_fks = False , sync_filter = None ): # noqa: C901
457457 """
458458 When deserializing a store model, we look at the deleted flags to know if we should delete the app model.
459459 Upon loading the app model in memory we validate the app models fields, if any errors occurs we follow
460460 foreign key relationships to see if the related model has been deleted to propagate that deletion to the target app model.
461461 We return:
462462 None => if the model was deleted successfully
463463 model => if the model validates successfully
464+
465+ :param fk_cache: A cache for foreign key lookups
466+ :type fk_cache: dict
467+ :param defer_fks: Whether to defer foreign key lookups
468+ :type defer_fks: bool
469+ :param sync_filter: The current sync's filter, if any
470+ :type sync_filter: Filter|None
464471 """
465472 deferred_fks = {}
466473 klass_model = syncable_models .get_model (self .profile , self .model_name )
@@ -476,18 +483,20 @@ def _deserialize_store_model(self, fk_cache, defer_fks=False): # noqa: C901
476483 klass_model .syncing_objects .filter (id = self .id ).delete ()
477484 return None , deferred_fks
478485 else :
486+ if sync_filter :
487+ print ("Has filter" , sync_filter )
479488 # load model into memory
480- app_model = klass_model .deserialize (json .loads (self .serialized ))
489+ app_model = klass_model .deserialize (json .loads (self .serialized ), sync_filter = sync_filter )
481490 app_model ._morango_source_id = self .source_id
482491 app_model ._morango_partition = self .partition
483492 app_model ._morango_dirty_bit = False
484493
485494 try :
486495 # validate and return the model
487496 if defer_fks :
488- deferred_fks = app_model .deferred_clean_fields ()
497+ deferred_fks = app_model .deferred_clean_fields (sync_filter = sync_filter )
489498 else :
490- app_model .cached_clean_fields (fk_cache )
499+ app_model .cached_clean_fields (fk_cache , sync_filter = sync_filter )
491500 return app_model , deferred_fks
492501
493502 except (exceptions .ValidationError , exceptions .ObjectDoesNotExist ) as e :
@@ -853,15 +862,31 @@ def delete(
853862 obj ._update_hard_deleted_models ()
854863 return collector .delete ()
855864
856- def cached_clean_fields (self , fk_lookup_cache ):
865+ def clean_fields (self , exclude = None , sync_filter = None ):
866+ """
867+ Immediately validates all fields
868+
869+ :param exclude: A list of field names to exclude from validation
870+ :type exclude: list[str]
871+ :param sync_filter: The current sync's filter, if any
872+ :type sync_filter: Filter|None
873+ """
874+ super (SyncableModel , self ).clean_fields (exclude = exclude )
875+
876+ def cached_clean_fields (self , fk_lookup_cache , exclude = None , sync_filter = None ):
857877 """
858878 Immediately validates all fields, but uses a cache for foreign key (FK) lookups to reduce
859879 repeated queries for many records with the same FK
860880
861881 :param fk_lookup_cache: A dictionary to use as a cache to prevent querying the database if a
862882 FK exists in the cache, having already been validated
883+ :type fk_lookup_cache: dict
884+ :param exclude: A list of field names to exclude from validation
885+ :type exclude: list[str]
886+ :param sync_filter: The current sync's filter, if any
887+ :type sync_filter: Filter|None
863888 """
864- excluded_fields = []
889+ excluded_fields = exclude or []
865890 fk_fields = [
866891 field for field in self ._meta .fields if isinstance (field , models .ForeignKey )
867892 ]
@@ -883,7 +908,7 @@ def cached_clean_fields(self, fk_lookup_cache):
883908 fk_lookup_cache [key ] = 1
884909 excluded_fields .append (f .name )
885910
886- self .clean_fields (exclude = excluded_fields )
911+ self .clean_fields (exclude = excluded_fields , sync_filter = sync_filter )
887912
888913 # after cleaning, we can confidently set ourselves in the fk_lookup_cache
889914 self_key = "{id}_{db_table}" .format (
@@ -892,15 +917,19 @@ def cached_clean_fields(self, fk_lookup_cache):
892917 )
893918 fk_lookup_cache [self_key ] = 1
894919
895- def deferred_clean_fields (self ):
920+ def deferred_clean_fields (self , exclude = None , sync_filter = None ):
896921 """
897922 Calls `.clean_fields()` but excludes all foreign key fields and instead returns them as a
898923 dictionary for deferred batch processing
899924
925+ :param exclude: A list of field names to exclude from validation
926+ :type exclude: list[str]
927+ :param sync_filter: The current sync's filter, if any
928+ :type sync_filter: Filter|None
900929 :return: A dictionary containing lists of `ForeignKeyReference`s keyed by the name of the
901930 model being referenced by the FK
902931 """
903- excluded_fields = []
932+ excluded_fields = exclude or []
904933 deferred_fks = defaultdict (list )
905934 for field in self ._meta .fields :
906935 if not isinstance (field , models .ForeignKey ):
@@ -918,7 +947,7 @@ def deferred_clean_fields(self):
918947 )
919948 )
920949
921- self .clean_fields (exclude = excluded_fields )
950+ self .clean_fields (exclude = excluded_fields , sync_filter = sync_filter )
922951 return deferred_fks
923952
924953 def serialize (self ):
@@ -939,8 +968,14 @@ def serialize(self):
939968 return data
940969
941970 @classmethod
942- def deserialize (cls , dict_model ):
943- """Returns an unsaved class object based on the valid properties passed in."""
971+ def deserialize (cls , dict_model , sync_filter = None ):
972+ """Returns an unsaved class object based on the valid properties passed in.
973+
974+ :param dict_model: The model data to deserialize
975+ :type dict_model: dict
976+ :param sync_filter: The current sync's filter, if any
977+ :type sync_filter: Filter|None
978+ """
944979 kwargs = {}
945980 for f in cls ._meta .concrete_fields :
946981 if f .attname in dict_model :
0 commit comments