django - comparing old and new field value before saving django - comparing old and new field value before saving python python

django - comparing old and new field value before saving


There is very simple django way for doing it.

"Memorise" the values in model init like this:

def __init__(self, *args, **kwargs):    super(MyClass, self).__init__(*args, **kwargs)    self.initial_parametername = self.parametername    ---    self.initial_parameternameX = self.parameternameX

Real life example:

At class:

def __init__(self, *args, **kwargs):    super(MyClass, self).__init__(*args, **kwargs)    self.__important_fields = ['target_type', 'target_id', 'target_object', 'number', 'chain', 'expiration_date']    for field in self.__important_fields:        setattr(self, '__original_%s' % field, getattr(self, field))def has_changed(self):    for field in self.__important_fields:        orig = '__original_%s' % field        if getattr(self, orig) != getattr(self, field):            return True    return False

And then in modelform save method:

def save(self, force_insert=False, force_update=False, commit=True):    # Prep the data    obj = super(MyClassForm, self).save(commit=False)    if obj.has_changed():        # If we're down with commitment, save this shit        if commit:            obj.save(force_insert=True)    return obj


It is better to do this at ModelForm level.

There you get all the Data that you need for comparison in save method:

  1. self.data : Actual Data passed to the Form.
  2. self.cleaned_data : Data cleaned after validations, Contains Data eligible to be saved in the Model
  3. self.changed_data : List of Fields which have changed. This will be empty if nothing has changed

If you want to do this at Model level then you can follow the method specified in Odif's answer.


Also you can use FieldTracker from django-model-utils for this:

  1. Just add tracker field to your model:

    tracker = FieldTracker()
  2. Now in pre_save and post_save you can use:

    instance.tracker.previous('modelfield')     # get the previous valueinstance.tracker.has_changed('modelfield')  # just check if it is changed