Django: Before a model is updated, I'd like to “look at” its previous attributes

后端 未结 5 708
星月不相逢
星月不相逢 2021-02-13 16:36

When an update/create is performed on a Django model (.save()) I would like to be able to \"step in\" and compare some particular attributes to what they were set t

5条回答
  •  粉色の甜心
    2021-02-13 17:25

    Here's my idea: play around with properties.

    Say you have this class:

    class Foo(models.Model):
        name = models.CharField()
    

    Instead, rename your field (you won't need a migration if it's the first time you're doing this) and:

    class Foo(models.Model):
        _name = models.CharField()
    
        @property
        def name(self):
            return self._name
    
        @name.setter
        def name(self, new_value):
            if not getattr(self, '_initial_name', False):
                self._initial_name = self._name
    
            if new_value != self._initial_name:
                self._name_changed = True
            else:
                self._name_changed = False
    
            self._name = new_value
    

    We added two attributes to your Foo instances: '_initial_name' and '_name_changed' and a property: 'name'. These are not model fields and will never be saved to the database. Also, you won't have to mess with the '_name' field any longer as long as the 'name' property takes care of everything.

    Now, your 'pre_save' or 'post_save' signal handler can make checks on what has changed:

    def handle_pre_save(sender, **kwargs):
        foo = kwargs['instance']
        if getattr(foo, '_name_changed', False):
            log.debug("foo changed its name from '%s' to '%s'",
                      foo._initial_name, foo.name)
    

提交回复
热议问题