django-fsm
django-fsm copied to clipboard
`Model.refresh_from_db` doesn't work with protected option
If there is FSMField field with protected=True in django model then refresh_from_db method will fail with AttributeError exception.
class ProtectedAccessModel(models.Model):
status = FSMField(default='new', protected=True)
instance = ProtectedAccessModel()
instance.save()
instance.refresh_from_db() # <-- AttributeError will be raised
For my point of view this is a major issue. refresh_from_db used widely and supposed to work in any cases.
duplicate of #89 and documented in #91, although i would definitely appreciate the fix you provide in your PR.
As you can see the solution fastly became too complicated.
This is my current overridden refresh_from_db that I use for a workaround. This is for a model that has a single django-fsm field named status:
def refresh_from_db(self, using=None, fields=None):
"""
Reload instance from database
but avoid writing to self.status, directly.
"""
if fields is None:
refresh_status = True
fields = [f.name for f in self._meta.concrete_fields]
else:
refresh_status = 'status' in fields
fields_without_status = [f for f in fields if f != 'status']
with transaction.atomic():
super().refresh_from_db(using=using, fields=fields_without_status)
if refresh_status:
fresh_status = type(self).objects.only('status').get(pk=self.pk).status
self._meta.get_field('status').set_state(self, fresh_status)
Since all possible solutions are hacky and thread/async unsafe this one of the reason why the alternative fsm implementation was created
https://docs.viewflow.io/fsm/index.html