0

I am using Django for a web application and I want to implement some code to detect changes in my model (and use that to update the model). I have fiddled with save:

class MyModel(models.Model):
    def save(self, *args, **kw):
        if self.somevalue == 0:
            self.someothervalue = timezone.now()
        else:
            self.someothervalue = None

        super(MyModel, self).save(*args, **kw)

but this will also update someothervalue to timezone.now() when somevalue already was 0. I want it only to update if it becomes 0.

How do I do that?

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195

2 Answers2

1

Not tested but should work. You cache the previous value inside __init__ and detect if it has changed inside save.

class MyModel(models.Model):

    def __init__(self, *args, **kwargs):
        super(MyModel, self).__init__(*args, **kwargs)
        self.prev_somevalue  = self.somevalue

    def save(self, *args, **kw):
        if self.somevalue == 0 and self.prev_somevalue != self.somevalue:
            self.someothervalue = timezone.now()
        else:
            self.someothervalue = None

        super(MyModel, self).save(*args, **kw)

Alternatively, if you are using forms you could do that on the ModelForm level by using the changed_data property.

Lastly, if you want to use signals, you should use the pre_save signal and retreive the previous from the database.

zxzak
  • 8,985
  • 4
  • 27
  • 25
1

I prefer this way of checking for changes in the save method:

class MyModel(models.Model)

    def save(self, *args, **kwargs):
        db_object = MyModel.objects.get(id=self.id) # this is the copy of the object saved in the database
        if self.somevalue == 0 and db_object.somevalue != 0:
            self.someothervalue = timezone.now()
        else:
            self.someothervalue = None

        super(MyModel, self).save(*args, **kwargs)
wobbily_col
  • 11,390
  • 12
  • 62
  • 86