Author: | Chris Chambers |
---|---|
Date: | 2012/05/08 |
Django Audited Models provides a simple abstract base class (and factory function) for tracking database record creation and modification times, as well as the creator of the record and the last user to edit it. It leverages two pluggable applications to achieve this:
- Django Extensions, which provides (amongst many other things) a
CreationDateTimeField
andModificationDateTimeField
. - Django Threaded Multihost, originally developed for Satchmo, which
provides a
threadlocals
mechanism that works reliably for Django installations powering multiple sites via thesites
framework.
- Install pip.
- Run
pip install django-audited-models
. - Add
threaded_multihost.middleware.ThreadLocalMiddleware
to your list ofMIDDLEWARE_CLASSES
. - Inherit from
AuditedModel
instead ofmodels.Model
in your django applications. - Profit!
Django-audited-models fulfils several needs:
- This kind of metadata is almost always useful, and inexpensive to capture - most of your clients will just presume this information is logged and will be frustrated if they can't get at it ("What do you mean we can't see who created this record?")
- Django's admin logging functionality provides some of this detail, but is flawed in that it only captures events which take place within the admin itself.
- This app provides a consistent, logical naming convention and interface for the metadata.
- This app makes use of several other applications to capture this
information automatically. No need to pollute your views with unrelated
logic or override
ModelAdmin
methods to store the user who created the record. - It's pluggable - simply drop it in, install its requirements, inherit from
AuditedModel
, and you'll have your creation/modification dates and the users responsible for them, respectively. Similarly, replace yourModelAdmin
with theAuditedAdmin
subclass and you'll have some sensible defaults for the admin UI (readonly metadata fields, etc.). - As a bonus, ensures that
MyModel.objects.latest()
does something sensible by default - very handy when working with the interpreter, especially.
Some might question the verbosity of the time entry fields
(datetime_created
and datetime_modified
). Consider the following:
>>> from datetime import date >>> latest_user = User.objects.latest('date_joined') >>> if latest_user.date_joined < date.today(): >>> print "Nobody has joined the site today." # Intuitively, this looks like it will work, but... TypeError: can't compare datetime.datetime to datetime.date
Python treats datetime
objects very differently to dates
, and the
explicit fieldnames remind the developer of this difference and help prevent
errors due to incorrect assumptions.
- Python 2.5+
- Django 1.2+
- Applications listed in
requirements.txt
You will also need to install the applications listed in
requirements-dev.txt
in order to run the test suite.