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 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.