I recently had a software requirement in which I needed to send a notification when a model attribute changed. I looked a few third party projects, but they either did not do what I need or were not maintained, so I decided to role my own. Here is the solution, I came up with, via a Mixin:

import datetime

class DirtyMixin(object):
@property
def is_dirty(self):
dirty_fields = []
is_dirty = False
if self.pk:
db_obj = self.__class__.objects.get(id=self.pk)
for f in self._meta.local_fields:
if(self.__getattribute__(f.name),datetime):
try:
attribute = self.__getattribute__(f.name)
if attribute != db_obj.__getattribute__(f.name):
dirty_fields.append(f.name)
is_dirty = True
except TypeError:
pass

return is_dirty, dirty_fields

If you want to use this, you can added a django signal to fire on Model.pre_save and you would add some code like this:

@staticmethod
def pre_save(sender, **kwargs):
from apps.accounts.models import User

instance = kwargs.get('instance')
created = kwargs.get('created')

is_dirty, dirty_fields = instance.is_dirty
if is_dirty:
# blah blah blah
...

models.signals.pre_save.connect(YOURMODEL.pre_save, sender=YOURMODEL)

If any model field has changed, then is_dirty will return True and dirty_fields will contain the field names of the fields that were updated.