11from __future__ import absolute_import , unicode_literals
22
33import copy
4+ import functools
45import hashlib
56import logging
67import time
@@ -44,8 +45,8 @@ def class_prepared_concurrency_handler(sender, **kwargs):
4445
4546 if hasattr (sender , 'ConcurrencyMeta' ):
4647 sender ._concurrencymeta .enabled = getattr (sender .ConcurrencyMeta , 'enabled' , True )
47- check_fields = getattr (sender .ConcurrencyMeta , 'check_fields' , [] )
48- ignore_fields = getattr (sender .ConcurrencyMeta , 'ignore_fields' , [] )
48+ check_fields = getattr (sender .ConcurrencyMeta , 'check_fields' , None )
49+ ignore_fields = getattr (sender .ConcurrencyMeta , 'ignore_fields' , None )
4950 if check_fields and ignore_fields :
5051 raise ValueError ("Cannot set both 'check_fields' and 'ignore_fields'" )
5152
@@ -310,6 +311,19 @@ def inner(self, force_insert=False, force_update=False, using=None, **kwargs):
310311 return update_wrapper (inner , func )
311312
312313
314+ def filter_fields (instance , field ):
315+ if not field .concrete :
316+ # reverse relation
317+ return False
318+ if field .is_relation and field .related_model is None :
319+ # generic foreignkeys
320+ return False
321+ if field .many_to_many and instance .pk is None :
322+ # can't load remote object yet
323+ return False
324+ return True
325+
326+
313327class ConditionalVersionField (AutoIncVersionField ):
314328 def contribute_to_class (self , cls , name , virtual_only = False ):
315329 super (ConditionalVersionField , self ).contribute_to_class (cls , name , virtual_only )
@@ -333,10 +347,11 @@ def _get_hash(self, instance):
333347 check_fields = instance ._concurrencymeta .check_fields
334348 ignore_fields = instance ._concurrencymeta .ignore_fields
335349
350+ filter_ = functools .partial (filter_fields , instance )
336351 if check_fields is None and ignore_fields is None :
337- fields = sorted ([f .name for f in instance ._meta .get_fields ()])
352+ fields = sorted ([f .name for f in filter ( filter_ , instance ._meta .get_fields () )])
338353 elif check_fields is None :
339- fields = sorted ([f .name for f in instance ._meta .get_fields ()
354+ fields = sorted ([f .name for f in filter ( filter_ , instance ._meta .get_fields () )
340355 if f .name not in ignore_fields ])
341356 else :
342357 fields = instance ._concurrencymeta .check_fields
0 commit comments