Open-source project
jazzband/django-auditlog avatar
jazzband/django-auditlog

jazzband/django-auditlog: a change log for Django models that stores a summary, not a version history

A Django app that keeps a log of changes made to an object.

1,389 stars456 forksPythonMIT

At a glance

What is it?
django-auditlog is a MIT licensed Django app that records changes made to your models along with the user who made them, keeping its dependencies to Django and python-dateutil and saving the changes as a JSON summary. The reasoning is stated plainly: existing solutions offered version control, which was found excessive and expensive in storage and performance.
Who is it for?
Adopt django-auditlog if you need to know who changed a model record and what changed, without building a versioning layer, since the app is small, has two dependencies and stores a JSON summary rather than a full history of every field. Do not adopt it if you need point in time recovery of a row, because the design explicitly rejects version control as excessive in storage and performance.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • jazzband/django-auditlog1,389 ★ · +2
Star history
Repository2026-10-172026-11-07
jazzband/django-auditlog1.4k1.4k

2 Stars in the last 21 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The origin story is a rejection of version control

The README explains why the app exists, and the explanation is the most useful part of it.

Auditlog was created out of the need for a simple Django app that logs changes to models along with the user who made the changes, later referred to as actor. The reason it was written is that existing solutions seemed to offer a type of version control, which was found excessive and expensive in terms of database storage and performance.

That is the whole design brief, and it is a rejection rather than an improvement. A version control system for your models stores previous versions of rows, which means an unbounded number of rows that grow with every edit, and the cost of that is paid on every write. Auditlog's position is that most applications need to know who did what and when, not to be able to reconstruct the exact state of a row from six months ago, and that the difference in storage and query cost between the two approaches is not worth paying when you do not need the second.

So the log is an audit trail, not a history. That distinction is the thing to hold on to when you decide whether this is the right tool, because it determines the questions you can answer with it later.

Like the admin log, but more flexible and in JSON

The core idea of Auditlog is described as similar to the log from Django's admin, with the difference that Auditlog is much more flexible. It also saves a summary of the changes in JSON format, so changes can be tracked easily.

Two properties follow from that. The first is that a change is recorded as a summary rather than as a row image, which is the storage argument again, and it also has a practical effect: a change record is something you can read, diff and display without reconstructing state.

The second is the JSON. Storing the change summary as JSON rather than as a set of typed columns is what keeps the schema stable across applications, since the fields that change differ per model, and it is what lets the log be queried and rendered generically. The repository's package list shows the mechanism, with an `auditlog` package containing `migrations`, `management` and `management.commands` subpackages and a `templatetags` subpackage, and the template tags are what render a change summary in a Django template, which is how a project would show the history on a detail page.

The documentation is on Read the Docs, with the source in the `docs` folder of the repository, and there is a dedicated upgrade page for version 3 that the README tells you to read before upgrading to that line.

Two dependencies, and a wide compatibility matrix

The stated goal is to use as much of Python and Django's built in functionality as possible to keep the list of dependencies as short as possible, and the packaging reflects that.

The `install_requires` list has two entries, `Django>=4.2` and `python-dateutil>=2.7.0`. Two dependencies is remarkable for an app that touches model signals, and it is the clearest signal of what the author was trying to avoid, namely a package that drags in a stack of its own and needs upgrading on its own schedule.

The supported versions are broad. `python_requires` is `>=3.10`, and the classifiers list Python 3.10 through 3.14 and Django 4.2, 5.0, 5.1, 5.2 and 6.0. So a project on an older Python, or on Django before 4.2, is out of scope, and a project on the newest Django is in scope, which is the right order of bias for a library that gets adopted into long lived applications.

The other packaging detail worth knowing is the version scheme. The setup script uses `use_scm_version` with a post-release scheme, so the version number comes from the git tag rather than being written in a file, and the project is a Jazzband project, which is why the release build publishes both a tgz and a wheel.

The licence is MIT, the author is Jan-Jelle Kester, and the package description is as plain as it gets, an audit log app for Django.

The release process is a seven step checklist

The README documents its own release process, which is unusual and useful, because it tells you how a version gets made and therefore what you can expect from a release.

The steps are: make sure all tests on master are green, create a branch `vX.Y.Z` from master for that specific release, update the CHANGELOG release date, open a pull request from `vX.Y.Z` to master, and as project lead, once that is merged, create and push the tag `vX.Y.Z`, which triggers the release build and a notification from Jazzband that the two packages, a tgz and a wheel, are available. Then test the install, and publish the release to PyPI.

Two details in that list are worth pulling out. The release branch is created from master and the tag comes after the merge, so the tag always points at a commit that was on master, which is the basic discipline that keeps a release reproducible. And the step where the maintainer tests the install after the build is a manual step that most projects skip, and its presence tells you how seriously the releases are taken.

The recent tags are v3.3.0 on 2025-10-02, v3.4.0 on 2025-12-04 and v3.4.1 on 2025-12-18, and the last push to the repository was on 2026-10-12, so the code is still being worked on even though the last tagged release is from the end of 2025. The repository is not archived, and the licence and documentation links are all in place, with a `CHANGELOG.md`, a `CONTRIBUTING.md`, a `CODE_OF_CONDUCT.md`, a `Makefile` and a `tox.ini` in the tree.

The Makefile is mostly about translations

The Makefile is small and its default goal is a help target that greps the file for the comment annotations, so `make` with no arguments lists the available commands.

There are two functional groups. `install` runs `pip install -e .` for an editable install, and `test` runs `./runtests.sh`, which is the test entry point the repository ships separately.

The rest is internationalisation, and it is a substantial part of the project's surface. `makemessages` extracts translatable strings and creates or updates the `.po` files for all languages, with `--add-location=file` and ignoring `__pycache__` and migrations. `compilemessages` compiles the `.po` files into `.mo`. `create-locale` creates the initial locale structure for a new language and requires a `LANG` parameter, with the error message naming the usage as `make create-locale LANG=<language_code>` and giving `ko` and `ja` as examples. And `i18n` is the convenience target that runs both.

That an audit log application carries full translation infrastructure is a small but telling detail. It is the kind of app that gets embedded in an internal tool for a company in one country and then in another, and shipping the message catalogues from the start is cheaper than retrofitting them.

The formatting configuration is minimal and modern, with Black configured for Python 3.9 as the target version and isort set to the black profile, and a `.pre-commit-config.yaml` at the top level, so the style is enforced before the code reaches review.

Where django-auditlog is the wrong choice

The first wrong case is point in time recovery. If your requirement is to restore a record to what it looked like last March, Auditlog is the wrong tool by design, because the author's own reasoning is that version control is excessive and expensive. The log tells you what changed and who changed it, and if you need the old value, you need a different design, or a different tool, or a change to how you store your history.

The second wrong case is a compliance trail that has to be tamper evident. Nothing in the documentation describes an append only store, a hash chain or an external write, and a log table in the same database as the data it records is, structurally, editable by the same credentials. If the requirement is that the record cannot be altered by an administrator with database access, that is a property to design for rather than to assume from an audit log.

The third is a project whose actor model does not fit. The app logs the user who made the change, and how that user is resolved is the part of the integration that your project owns, and if your users are not Django auth users, or if you need to log actions taken by a scheduled job or a service account, that is configuration work rather than a one line switch.

The fourth is a project that is not on a supported Django. The floor is Django 4.2 on Python 3.10, so an application pinned to an older Django has to stay on an older release of the app, and the README's own instruction to read the v3 upgrade guide before moving is a hint that the major version boundary has real changes behind it.

Editorial conclusion

Adopt django-auditlog if you need to know who changed a model record and what changed, without building a versioning layer, since the app is small, has two dependencies and stores a JSON summary rather than a full history of every field. Do not adopt it if you need point in time recovery of a row, because the design explicitly rejects version control as excessive in storage and performance. Verify first that the Django version you run is in the supported range, from 4.2 through 6.0 on Python 3.10 to 3.14, read the upgrade guide before moving to the v3 line since the README asks you to, and check that the actors model in your project can be resolved by the app before you rely on it for a compliance trail.

Frequently asked questions

What does django-auditlog record?

It is a reusable Django app that logs changes made to your models together with the user who made them, the actor, and saves a summary of the changes in JSON format so that changes can be tracked easily. The core idea is similar to the log in Django's admin, but more flexible.

Which Python and Django versions does django-auditlog support?

Python 3.10 and newer, and Django 4.2, 5.0, 5.1, 5.2 and 6.0 according to the package classifiers, with `install_requires` of `Django>=4.2` and `python-dateutil>=2.7.0` and `python_requires` of `>=3.10`.

Is django-auditlog a version control system for models?

No, and that is the stated design reason for the project. Auditlog was created because existing solutions seemed to offer a type of version control, which was found excessive and expensive in terms of database storage and performance, so it logs who changed what rather than storing previous versions of rows.

How do I run the tests for django-auditlog?

The Makefile's test target runs `./runtests.sh`, and `make install` performs an editable install with `pip install -e .` first. The repository also carries a tox.ini for multi environment runs and a codecov badge for coverage.

Should I read anything before upgrading django-auditlog to version 3?

Yes. The README points to an Upgrading to version 3 page in the documentation and asks you to check it before upgrading to V3, and the project version is derived from the git tag with setuptools_scm rather than written in the packaging file.

Official sources

  1. Issues
  2. jazzband/django-auditlog on GitHub
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jazzband-django-auditlog.svg)](https://hysenlabs.com/projects/jazzband-django-auditlog)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/jazzband-django-auditlog.svg)](https://hysenlabs.com/projects/jazzband-django-auditlog)

Was this useful?