Easily Track Data Changes In Your Django Models

December 14, 2013 • Peter Sanchez

It's pretty common to want to know when specific data has been changed in a Django model. The Django admin itself will keep a log of changes made from the admin interface. That's very useful but not all data changes are made from the admin. While there are a handful of existing applications to track data changes, they can often be overkill, or flat out not be a good fit, depending on the use case or business requirements. For example, a client who runs a content site wanted the ability to change the slug of a piece of content, which effects it's URL, and automatically create a redirect from the old slug to the new one. Another simple example is for an internal time tracking / project management tool we built that we call Grinch. When one of us updates/changes a time log entry we want to create a simple note on the entry with what was changed. We don't want revision tracking, etc. just a simple note for information purposes. So, let's talk about how you can add this sort of tracking in a few quick steps. Using Django's post_init signal is probably the easiest way to grab the starting data and store it on the model instance. Let's go with our Grinch example. This is a simplified version of what our code is actually doing, but it's pretty self explanatory. Easy enough right? Whenever an existing TimeLog instance is initialized the signal will be fired and the "timelog_post_init" function will assign the _original_* fields to the instance. Once the instance is saved, the "add_track_save_note" method is called which will save a note with the updated fields (if any fields actually changed). Now when a project manager needs to know why, or what, was changed in a previously saved time log entry, they just go view the entries and it will display the note like so:
timelog_example.png
We realize this may duplicate work that's been done in an existing OSS app but our goal is to create the best fit for the given business need. Sometimes these smaller implementations are the perfect way to scratch that itch.

Have a response?

Start a discussion on the mailing list by sending an email to
~netlandish/blog-discussion@lists.code.netlandish.com.