0

I have a model like this one:

class Exam(BaseModel):
    ...
    STATE_CHOICES = (
        (PASS, PASS),
        (FAILED, FAILED),
        (GREAT, GREAT),
    state = models.CharField(max_length=15, choices=STATE_CHOICES, default=PASS)
    ...

Now I want orderride the save method and know if the state field is changed or not:

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if self.__state != self.state:
            print('changed')
        super().save(force_insert, force_update, using, update_fields)

The self.__state seems wrong, how can I do that?

Mehdi Aria
  • 99
  • 9
  • You want to know it the `state` field changed from what? You mean, if it is set to something other than the default value? Or do you mean if it is different than what is in the database? Please formulate a more precise question. – Daniil Fajnberg Aug 23 '22 at 11:51
  • 2
    Does this answer your question? [When saving, how can you check if a field has changed?](https://stackoverflow.com/questions/1355150/when-saving-how-can-you-check-if-a-field-has-changed) – nigel239 Aug 23 '22 at 12:05
  • I got the answer from @ilyasbbu but I don't know I get 'NoneType' object has no attribute 'attname' – error – Mehdi Aria Aug 23 '22 at 12:10

3 Answers3

1

Essentially, you want to override the init method of models.Model so that you keep a copy of the original value. This makes it so that you don't have to do another DB lookup (which is always a good thing).

class Exam(models.Model):
    STATE_CHOICES = (
    ("PASS", "PASS"),
    ("FAILED", "FAILED"),
    ("GREAT", "GREAT"),)
    state = models.CharField(max_length=15, choices=STATE_CHOICES, default="PASS")

    __original_state = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__original_state = self.state

    def save(self, force_insert=False, force_update=False, *args, **kwargs):
        if self.state != self.__original_state:
            print("changed")
            # state changed - do something here

        super().save(force_insert, force_update, *args, **kwargs)
        self.__original_state = self.state
ilyasbbu
  • 1,468
  • 4
  • 11
  • 22
1

This question has been thoroughly solved and discussed in this thread including the edge cases, limitations and benefits of each approach.

0

There is no need to write this yourself. Use the Fieldtracker from the model_utils package to check if data has changed: https://django-model-utils.readthedocs.io/en/latest/utilities.html#field-tracker

hendrikschneider
  • 1,696
  • 1
  • 14
  • 26