Django Models Logging
This package logs every change to your Django models in the following format:
{
"field_name": {
"old": "old_value",
"new": "new_value"
}
}
For deleted objects, "new" is omitted and only "old" is stored.
Example:
{
"price": {
"old": "2425",
"new": "645"
},
"name": {
"old": "ProductName",
"new": "NewProductName"
}
}
Requirements
- Python >= 3.10
- Django >= 5.2
Installation
- Install via pip:
pip install django-models-logging
- Add to
INSTALLED_APPS— must be at the end, after all apps whose models you want to log:
INSTALLED_APPS = [
...,
'models_logging',
]
- Run migrations:
python manage.py migrate
Configuration
Select models to log
LOGGING_MODELS = (
'app.ClassName', # log only this model
'another_app', # log all models in this app
)
Exclude models from logging
LOGGING_EXCLUDE = (
'app', # exclude all models in this app
'another_app.Model', # exclude a specific model
)
Custom user model
If request.user is not your AUTH_USER_MODEL:
LOGGING_USER_MODEL = 'yourapp.Users'
# default: AUTH_USER_MODEL
Per-model field filtering
Set these as class attributes on the model:
class MyModel(models.Model):
LOGGING_IGNORE_FIELDS = ('field1', 'field2') # exclude specific fields
# OR
LOGGING_ONLY_FIELDS = ('field1', 'field2') # include only these fields
Merging changes per request
By default, each .save() call creates a separate Change record. If .save() is called multiple times in one request, use the middleware to merge them:
MIDDLEWARE = [
...,
'models_logging.middleware.LoggingStackMiddleware',
]
To control merging independently of the middleware:
LOGGING_MERGE_CHANGES = True # default: True
For scripts or Celery tasks outside of a request cycle, use the context manager:
from models_logging.utils import create_merged_changes
def your_task():
with create_merged_changes():
...
To temporarily suppress logging entirely:
from models_logging.utils import ignore_changes
with ignore_changes(): # ignore all models
...
with ignore_changes([MyModel]): # ignore specific models
...
Logging bulk updates
queryset.update() does not trigger Django signals and is not logged automatically. Use create_changes_for_update instead:
from models_logging.utils import create_changes_for_update
create_changes_for_update(MyModel.objects.filter(active=True), active=False)
This captures old and new values for each affected row.
Admin
To show an object's change history in the Django admin, use HistoryAdmin:
from models_logging.admin import HistoryAdmin
class YourModelAdmin(HistoryAdmin):
history_latest_first = False # show oldest first (default)
inline_models_history = '__all__' # '__all__' or list of inline model classes
Admin permissions
def can_revert(request, obj):
return request.user.is_superuser
LOGGING_REVERT_IS_ALLOWED = can_revert # callable or bool, default: True
LOGGING_CAN_DELETE_REVISION = False # callable or bool, default: False
LOGGING_CAN_DELETE_CHANGES = False # callable or bool, default: False
LOGGING_CAN_CHANGE_CHANGES = False # callable or bool, default: False
LOGGING_CHANGES_REVISION_LIMIT = 100 # max changes shown inline in a revision
Custom JSON encoder
The default encoder handles FieldFile and GeoDjango Point types. To use your own:
LOGGING_JSON_ENCODER = 'path.to.your.JsonEncoder'
Custom change extras
To store extra data with each change (e.g. request IP, correlation ID), provide a custom function:
# yourapp/logging.py
def get_change_extras(obj, action):
from models_logging import _local
return {
'ip': getattr(_local, 'request', None) and _local.request.META.get('REMOTE_ADDR'),
}
LOGGING_GET_CHANGE_EXTRAS_FUNC = 'yourapp.logging.get_change_extras'
Management command
Delete old change records:
# delete all changes
python manage.py delete_changes
# delete changes for specific content types (by id)
python manage.py delete_changes --ctype 1,2,3
# exclude content types from deletion
python manage.py delete_changes --ctype-exclude 4,5
# delete changes older than a date
python manage.py delete_changes --date_lte 2024.01.01
Version compatibility
| Package version | Django | Python |
|---|---|---|
| 5.2.x | 5.2 | 3.10 – 3.14 |
| 2.x | 3.1 – 4.1 | 3.8+ |
| 0.9.7 | <= 2.0 | — |
Note: This package is not a database backup solution. Reverting thousands of changes will be slow.
Release files for django-models-logging 5.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_models_logging-5.2.0.tar.gz | 16.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_models_logging-5.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.4 kB
Release files / django_models_logging-5.2.0.tar.gz
| Download URL | django_models_logging-5.2.0.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
92ca584336e6565323623996ab270983ea0261c837859ca506721801b4914885
|
|
BLAKE2b-256 checksum How to use checksums |
c8a3b353d4d64dbb50adae5fd988242d4b5c34c4af1bc16b9508bd1883ac93de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / django_models_logging-5.2.0-py3-none-any.whl
| Download URL | django_models_logging-5.2.0-py3-none-any.whl |
|---|---|
| Size | 27.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
80a5e52e8d7da03d8b2ee87fa8c35301eebe8b2c5fe05dbd1a465a8de5b52150
|
|
BLAKE2b-256 checksum How to use checksums |
81e03afd25144eca4c2576d5a527ef40881b12c72c0b2c335bf81492caaf9ad4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|