I need to detect when some of the fields of certain model have changed in the admin, to later send notifications depending on which fields changed and previous/current values of those fields.
I tried using a ModelForm
and overriding the save()
method, but the form's self.cleaned_data
and seld.instance
already have the new values of the fields.
Then in save method you can compare old and new value of field to check if the value has changed. @classmethod def from_db(cls, db, field_names, values): new = super(Alias, cls).
Use the has_changed() method on your Form when you need to check if the form data has been changed from the initial data.
The Django admin application can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the right data.
Modifying the answer above... taking the brilliant function from Dominik Szopa and changing it will solve your relationship change detection: Use this:
def get_changes_between_models(model1, model2, excludes = []):
changes = {}
for field in model1._meta.fields:
if not (field.name in excludes):
if field.value_from_object(model1) != field.value_from_object(model2):
changes[field.verbose_name] = (field.value_from_object(model1),
field.value_from_object(model2))
return changes
Then in your code you can say (avoid try/except for performance reasons):
if (self.id):
old = MyModel.Objects.get(pk=self.id)
changes = get_changes_between_models(self, old)
if (changes):
# Process based on what is changed.
If you are doing this at the "model" level, there is no way to save the extra query. The data has already been changed by the time you reach the "Save" point. My first post, so forgive me if I sound like an idiot.
To avoid extra DB lookup, I modified constructor to remember initial value and use this in save method later:
class Package(models.Model):
feedback = models.IntegerField(default = 0, choices = FEEDBACK_CHOICES)
feedback_time = models.DateTimeField(null = True)
def __init__(self, *args, **kw):
super(Package, self).__init__(*args, **kw)
self._old_feedback = self.feedback
def save(self, force_insert=False, force_update=False, *args, **kwargs):
if not force_insert and self.feedback != self._old_feedback:
self.feedback_time = datetime.utcnow()
return super(Package, self).save(force_insert, force_update, *args, **kwargs)
In order to get differences of two model instances, you can also use this function. It compare to model instances and returns dictionary of changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With