Django-simple-history is inserting new record on each save of target model. In docs the problem with F expressions is described. I try to circumvent this with overriden save method.
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# some other actions
self.refresh_from_db()
But it seems, that this is not working. Is the post_save
signal of base model called directly after super().save()
call? If so, is there a way to solve this problem keeping the F expression in target model update?
UPDATE: Saved instance has one of its attributes defined using an F expression, so this code is called in some other module:
instance.some_attribute = (F('some_attribute') + 15)
instance.save(update_fields=['some_attribute'])
This throws an error in django-simple-history's post_save
signal, when it tries to insert a extended copy of instance
to history table. I tried to refresh the instance in overriden save
method to get rid of the F expression in some_attribute
so the actual value is loaded. From the traceback it seems that the post_save
is called right after super().save()
call, before the refresh. Is it the way Django post_save with overriden save works? If so, is there a way to not change the update code (leave the update with F expression) and solve the history insert in model's save?
django-simple-history
provides signals for before and after the historical record is created: https://django-simple-history.readthedocs.io/en/2.7.0/signals.html
I suggest using these to update the instance before it gets saved to the historical table. Something like this should work:
from django.dispatch import receiver
from simple_history.signals import (
pre_create_historical_record,
post_create_historical_record
)
@receiver(pre_create_historical_record)
def pre_create_historical_record_callback(sender, **kwargs):
instance = kwargs["instance"]
history_instance = kwargs["history_instance"]
if isinstance(instance, ModelYouWantToRefresh)
instance.refresh_from_db()
history_instance.some_attribute = instance.some_attribute