Automatic model-level change tracking for Django. One mixin, one middleware, zero boilerplate.
Project description
django-audittrail
Automatic model-level change tracking for Django. One mixin, one middleware, zero boilerplate.
Records who changed what, when, from where — with full before/after field diffs.
Quick Start
1. Install
pip install django-audittrail
2. Add to INSTALLED_APPS
INSTALLED_APPS = [
...
'audittrail',
]
3. Add the middleware
MIDDLEWARE = [
...
'audittrail.middleware.AuditMiddleware', # after SessionMiddleware
...
]
4. Run migrations
python manage.py migrate
5. Add the mixin to your models
from audittrail import AuditableMixin
class Patient(AuditableMixin, models.Model):
name = models.CharField(max_length=200)
dob = models.DateField()
ssn = models.CharField(max_length=11)
class AuditTrail:
exclude_fields = ['updated_at']
mask_fields = ['ssn']
That's it. Every create, update, and delete on Patient is now tracked.
Querying Audit Logs
from audittrail.models import AuditLog
# All changes to a specific instance
AuditLog.objects.for_instance(patient)
# All changes by a user
AuditLog.objects.by_user(request.user)
# All changes to Patient model
AuditLog.objects.for_model(Patient)
# Time range
AuditLog.objects.between(start_datetime, end_datetime)
# Filter by action
AuditLog.objects.for_model(Patient).creates()
AuditLog.objects.for_model(Patient).updates()
AuditLog.objects.for_model(Patient).deletes()
Diff Format
log = AuditLog.objects.for_instance(patient).first()
print(log.changes)
# {"name": {"old": "John Doe", "new": "Jane Doe"},
# "dob": {"old": "1990-01-01", "new": "1990-06-15"}}
On CREATE, all fields have "old": null. On DELETE, all fields have "new": null.
Temporarily Disable Audit
import audittrail
with audittrail.disabled():
Patient.objects.bulk_create(patients_list)
Admin Integration
from audittrail.admin import AuditLogModelAdmin
@admin.register(Patient)
class PatientAdmin(AuditLogModelAdmin, admin.ModelAdmin):
pass
Configuration
Per-model (via AuditTrail inner class)
| Option | Description |
|---|---|
exclude_fields |
List of field names to skip in diffs |
mask_fields |
List of field names whose values are stored as "***" |
Global (via Django settings)
AUDITTRAIL = {
'ENABLED': True,
'GLOBAL_EXCLUDE_FIELDS': ['updated_at', 'modified_at'],
}
Requirements
- Python 3.10+
- Django 4.2+
Known Limitations
QuerySet.update()andbulk_create()bypass Django signals and are not tracked- Async (ASGI) context propagation is not yet supported
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dj_audittrail-0.1.0.tar.gz.
File metadata
- Download URL: dj_audittrail-0.1.0.tar.gz
- Upload date:
- Size: 15.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a44cd8d9ee503690d0e2256f15af2f9045f0eaeb5173db6b2f15a26ee0562da0
|
|
| MD5 |
ca32e5d5894f82cd9d3e62a040c26a4b
|
|
| BLAKE2b-256 |
7d86fae061d8cb7debc6e5b963b4eb969bb4d6fa3872fe52010fec1350804c03
|
File details
Details for the file dj_audittrail-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dj_audittrail-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb24fa4d7b19c7c76dc4f41a14c999938d6d0ee2e9065a65591f41a2ef53d0b5
|
|
| MD5 |
a804e080366a8f6ef59521f47e075599
|
|
| BLAKE2b-256 |
70f2d7ecfe3249b6f84eb8e80d745e876bf56f9296a6fd271020f3740362d2c5
|