@@ -471,6 +471,32 @@ def set_state(self, instance, state):
471
471
instance .__dict__ [self .attname ] = self .to_python (state )
472
472
473
473
474
+ class FSMModelMixin (object ):
475
+ """
476
+ Mixin that allows refresh_from_db for models with fsm protected fields
477
+ """
478
+
479
+ def _get_protected_fsm_fields (self ):
480
+ def is_fsm_and_protected (f ):
481
+ return isinstance (f , FSMFieldMixin ) and f .protected
482
+ protected_fields = filter (is_fsm_and_protected , self ._meta .concrete_fields )
483
+ return {f .attname for f in protected_fields }
484
+
485
+ def refresh_from_db (self , * args , ** kwargs ):
486
+ fields = kwargs .pop ("fields" , None )
487
+
488
+ # Use provided fields, if not set then reload all non-deferred fields.0
489
+ if not fields :
490
+ deferred_fields = self .get_deferred_fields ()
491
+ protected_fields = self ._get_protected_fsm_fields ()
492
+ skipped_fields = deferred_fields .union (protected_fields )
493
+
494
+ fields = [f .attname for f in self ._meta .concrete_fields
495
+ if f .attname not in skipped_fields ]
496
+
497
+ kwargs ['fields' ] = fields
498
+ super (FSMModelMixin , self ).refresh_from_db (* args , ** kwargs )
499
+
474
500
class ConcurrentTransitionMixin (object ):
475
501
"""
476
502
Protects a Model from undesirable effects caused by concurrently executed transitions,
0 commit comments