Reputation: 1382
thanks for your time.
I'm on Django 1.4, and I have the following code: Its the overriden save method for my Quest
model.
@commit_on_success
def save(self, *args, **kwargs):
from ib.quest.models.quest_status_update import QuestStatusUpdate
created = not self.pk
if not created:
quest = Quest.objects.get(pk=self)
# CHECK FOR SOME OLD VALUE
super(Quest, self).save(*args, **kwargs)
I couldn't find out a smart way of doing this. It seems very silly to me to have to make a new query for the object i'm currently updating in order to find out an old instance value.
Is there a better way to do this?
Thank you all.
Francisco
Upvotes: 17
Views: 11292
Reputation: 6825
You can store the old value inside the init method:
def __init__(self, *args, **kwargs):
super(MyModel, self).__init__(*args, **kwargs)
self.old_my_field = self.my_field
def save(self, *args, **kwargs):
print self.old_my_field
print self.my_field
You can probably use deepcopy or something alike to copy the whole object for later use in the save and delete methods.
Upvotes: 21
Reputation: 6272
I am checking the difference to old values using a django-reversion signal, but the same logic would apply to the save signals. The difference for me being that I want to save whether the field was saved or not.
@receiver(reversion.pre_revision_commit)
def it_worked(sender, **kwargs):
currentVersion = kwargs.pop('versions')[0].field_dict
fieldList = currentVersion.keys()
fieldList.remove('id')
commentDict = {}
print fieldList
try:
pastVersion = reversion.get_for_object(kwargs.pop('instances')[0])[0].field_dict
except IndexError:
for field in fieldList:
commentDict[field] = "Created"
comment = commentDict
except TypeError:
for field in fieldList:
commentDict[field] = "Deleted"
comment = commentDict
else:
for field in fieldList:
try:
pastTest = pastVersion[field]
except KeyError:
commentDict[field] = "Created"
else:
if currentVersion[field] != pastTest:
commentDict[field] = "Changed"
else:
commentDict[field] = "Unchanged"
comment = commentDict
revision = kwargs.pop('revision')
revision.comment = comment
revision.save()
kwargs['revision'] = revision
sender.save_revision
Upvotes: 1
Reputation: 44192
Django doesn't cache the old values of the model instance, so you need to do that yourself or perform another query before save.
One common pattern is to use a pre-save signal (or put this code directly in your save() method, as you've done):
old_instance = MyModel.objects.get(pk=instance.pk)
# compare instance with old_instance, and maybe decide whether to continue
If you want to keep a cache of the old values, then you would probably do that in your view code:
from copy import deepcopy
object = MyModel.objects.get(pk=some_value)
cache = deepcopy(object)
# Do something with object, and then compare with cache before saving
There was a recent discussion on django-developers about this as well, with some other possible solutions.
Upvotes: 12