Search code examples
pythondjangodjango-signals

django - comparing old and new field value before saving


I have a django model, and I need to compare old and new values of field BEFORE saving.

I've tried the save() inheritance, and pre_save signal. It was triggered correctly, but I can't find the list of actually changed fields and can't compare old and new values. Is there a way? I need it for optimization of pre-save actions.

Thank you!


Solution

  • 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
    

    Edit ( 06.05.2024 ): Please read through all the comments that have been added since I added this post 10 years ago. Things have changed, and though even I still use this approach myself and recommend using it, there are cases, where you need to tweak the approach or forgo using it. Again, read through the comments others have added.