Reproducing steps.
{{{
class AbstractBaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
@classmethod
def from_db(cls, db, field_names, values):
instance = super().from_db(db, field_names, values)
# save original values, when model is loaded from database
instance._initial_values = dict(zip(field_names, values,
strict=True))
return instance
}}}
To include the above DateTime fields in all models, just extend
it(AbstractBaseModel). Also, override the save method so that we can check
the value before saving the object. e.g. below
{{{
class Country(AbstractBaseModel):
name = models.CharField()
def save(self, *args, **kwargs):
if self.name != self._initial_values["name"]: # This will raise
AttributeError: 'Country' object has no attribute '_initial_values'
# `name` field value has changed/overridden. write
appropriate logic
print(f"New name: {self.name} and Old Name:
{self._initial_values["name"]}")
super().save(*args, **kwargs)
}}}
Above save method will raise the error as the parent class
(AbstractBaseModel) method hasn't been executed so the **_initial_values**
attribute won't be set. However, if you override the **from_db** method
inside the individual model classes, it would work. e.g.
{{{
class Country(AbstractBaseModel):
name = models.CharField()
def save(self, *args, **kwargs):
if self.name != self._initial_values["name"]: # This will work
# `name` field value has changed/overridden. write
appropriate logic
print(f"New name: {self.name} and Old Name:
{self._initial_values["name"]}")
super().save(*args, **kwargs)
@classmethod
def from_db(cls, db, field_names, values):
instance = super().from_db(db, field_names, values)
# save original values, when model is loaded from database
instance._initial_values = dict(zip(field_names, values,
strict=True))
return instance
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/35031>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* resolution: => invalid
--
Ticket URL: <https://code.djangoproject.com/ticket/35031#comment:1>