An introduction to Django Simple History

Wouldn’t it be useful if we could document changes in our life and revisit them later at will? It would allow us to better analyze situations, remember what we were thinking, or help us remember how we got to our current state. Although no such tool currently exists for changes in life, one such tool does exist in Django. It is called django-simple-history.
Django-simple-history stores Django model state on every create, update, or delete database operation; it can even revert back to old versions of a model, record which user changed a model, interact with multiple databases, and more. Rather than making code changes, django-simple-history gives us the ability to view and perform many of the changes via the admin interface.
Let’s imagine we are creating a simple Polling application and our
models.py
file looks like this:
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
published = models.BooleanField(default="False")
def __str__(self):
return self.question
How do we get django-simple-history to work on our application?
- Install django-simple-history:
pip install django-simple-history
- In the settings.py file, Add simple_history to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
'simple_history',
]
The historical models can track which user made each change. To
automatically populate the history user, add the
HistoryRequestMiddleware
to the project’s settings.
MIDDLEWARE = [
# ...
'simple_history.middleware.HistoryRequestMiddleware',
]
To track user changes without using the middleware, see django-simple-history’s user tracking alternative.
That is all that is required in the settings. Now, let’s return to the
models.py
file. To track history for a model we’ll need to import
HistoricalRecords
and create an instance of HistoricalRecords
on
that model. Each model needs its own historical records instance, this
gives us the flexibility to track or not track specific models.
- Import HistoricalRecords and create an instance as a model field
from django.db import models
from simple_history.models import HistoricalRecords # new line
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
published = models.BooleanField(default="False")
history = HistoricalRecords() # new line
def __str__(self):
return self.question
- Make and run migrations
python manage.py makemigrations
python manage.py migrate
Now all changes to the Poll model instance will be tracked in the database. Select a polling question and make changes to it. In this case let’s use Do you know of django-simple-history?
Then, click History on the top right corner to see [django-simple-history]{.title-ref} in action.
As we can see django-simple-history
has kept a log of changes that
have happened to this question. We can see that both users Ronard
and Luilly made changes, the date and time of the changes, and that
the user Luilly changed the polling question - all of this without
manually querying the database. Although django-simple-history
might
seem simple, its usefulness increases with the complexity of the model
and/or application. Imagine all the historical information it could give
you for a customer, claim or profile model in a large application.
There is a lot django-simple-history
allows us to do: track history
for a model you didn’t create (third-party
model),
generate an initial change for preexisting model
instances,
and more. See the official
documentation
for more.