Reputation: 768
I've got a Django model like so...
class Example(models.Model):
title = models.CharField(...)
...
I'm trying to compare two values - the title
field before the user changes it, and the title
after. I don't want to save both values in the database at one time (only need one title
field), so I'd like to use pre_save
and post_save
methods to do this. Is it possible to get the title before the save, then hold this value to be passed into the post_save
method?
The pre_save and post_save methods look like so...
@receiver(pre_save, sender=Example, uid='...')
def compare_title_changes(sender, instance, **kwargs):
# get the current title name here
x = instance.title
@receiver(post_save, sender=Example, uid='...')
def compare_title_changes(sender, instance, **kwargs):
# get the new title name here and compare the difference
x = instance.title # <- new title
if x == old_title_name: # <- this is currently undefined, but should be retrieved from the pre_save method somehow
...do some logic here...
Any ideas would be greatly appreciated!
Edit
As was pointed out to me, pre_save and post_save both occur after save() is called. What I was looking for is something like pre_save() but before the actual save method is called. I set this on the model so that the logic to be performed will be accessible wherever the instance is saved from (either admin or from a user view)
Upvotes: 1
Views: 3834
Reputation: 1980
We can only say object has changed if "save" method passes successfully, so post_save
is good to be sure that model object has updated.
Setting on the fly attribute on model class instance can do the task, as the same instance is passed from pre_save to post_save.
def set_flag_on_pre_save(sender, instance, *args, **kwargs):
# Check here if flag setting condition satisfies
set_the_flag = true
if set_the_flag:
instance.my_flag=0
def check_flag_on_post_save(sender, instance, *args, **kwargs):
try:
print(instance.my_flag)
print('Flag set')
except AttributeError:
print('Flag not set')
pre_save.connect(set_flag_on_pre_save, sender=ModelClass)
post_save.connect(check_flag_on_post_save, sender=ModelClass)
Upvotes: 1
Reputation: 6789
Use Example.objects.get(pk=instance.id)
to get the old title from the database in the pre_save
handler function:
@receiver(pre_save, sender=Example, uid='...')
def compare_title_changes(sender, instance, **kwargs):
new_title = instance.title # this is the updated value
old_title = Example.objects.get(pk=instance.id)
# Compare the old and new titles here ...
This trick was proposed here a long time ago. I've not tested it with the recent Django version. Please let me know whether it's still working.
Upvotes: 5