Django How to cleaify if the value is changed in models save method
Question:
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?
Answers:
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
This question has been thoroughly solved and discussed in this thread including the edge cases, limitations and benefits of each approach.
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
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?
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
This question has been thoroughly solved and discussed in this thread including the edge cases, limitations and benefits of each approach.
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