Audit every Django migration with diffs, timestamps, executor identity, and auto-generated rollback scripts.
Project description
django-migration-auditor
A Django package that logs every migration run with schema diffs, timestamps, executor identity, and generates rollback scripts automatically.
✨ Features
| Feature | Description |
|---|---|
| Full Audit Trail | Records every apply / unapply with app, migration name, direction, who ran it, environment, hostname, database alias, start/end timestamps, and duration. |
| Schema Diffs | Captures before/after schema snapshots via connection.introspection and stores a human-readable diff (tables, columns, indexes, constraints). |
| Auto Rollback Scripts | Generates .sql rollback scripts for each applied migration using SchemaEditor(collect_sql=True) — no subprocess, no side effects. |
| Management Commands | audit_migrations (list/filter/export), generate_rollback (on-demand SQL), migration_report (summary stats). |
| Django Admin | Read-only admin panel with colour-coded badges, collapsible schema diffs, date hierarchy, and full-text search. |
| Zero Config | Works out of the box — just add to INSTALLED_APPS and run migrate. |
| Fail-Safe | Audit failures never break real migrations. All recording is wrapped in try/except. |
📦 Installation
pip install django-migration-auditor
Or for development:
git clone https://github.com/abburisaikarthik/django-migration-auditor.git
cd django-migration-auditor
pip install -e ".[dev]"
🚀 Quick Start
1. Add to INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
# ...
"migration_auditor",
]
2. Run migrations
python manage.py migrate
This creates the migration_auditor_log table and starts auditing immediately.
3. View audit logs
# Table format (default)
python manage.py audit_migrations
# JSON
python manage.py audit_migrations --format json
# CSV
python manage.py audit_migrations --format csv
# Filter by app and status
python manage.py audit_migrations --app myapp --status failed --since 2024-01-01
4. View summary report
python manage.py migration_report
python manage.py migration_report --app myapp
5. Generate rollback scripts
# Save to file
python manage.py generate_rollback --app myapp --name 0002_add_field
# Print to stdout
python manage.py generate_rollback --app myapp --name 0002_add_field --stdout
6. Django Admin
Navigate to /admin/migration_auditor/migrationauditlog/ for a read-only view of all audit entries with:
- Colour-coded direction badges (▲ Apply / ▼ Unapply)
- Status badges (Success / Failed / In Progress)
- Collapsible schema diff and rollback SQL sections
- Date hierarchy, filters, and search
⚙️ Configuration
All settings are optional. Configure via the MIGRATION_AUDITOR dict in settings.py:
MIGRATION_AUDITOR = {
# Master switch — set to False to disable all auditing.
"ENABLED": True,
# Directory for .sql rollback files (relative to BASE_DIR or absolute).
"ROLLBACK_DIR": "rollbacks",
# Capture before/after schema snapshots.
"CAPTURE_SCHEMA_DIFF": True,
# Optional callable: (request) -> str to resolve the current user.
# Only useful with the optional middleware.
"USER_RESOLVER": None,
# Override automatic environment detection.
# When None, checks DJANGO_ENV → ENVIRONMENT → DJANGO_SETTINGS_MODULE.
"ENVIRONMENT": None,
# App labels to skip (never audit these).
"EXCLUDE_APPS": [],
# Max chars for schema diff storage. 0 = unlimited.
"MAX_DIFF_LENGTH": 0,
}
Environment Detection
The package auto-detects the environment by checking (in order):
MIGRATION_AUDITOR["ENVIRONMENT"]settingDJANGO_ENVenvironment variableENVIRONMENTenvironment variable- Keywords in
DJANGO_SETTINGS_MODULE(prod, staging, dev, test, local) - Falls back to
"unknown"
User Detection
The executor identity is resolved by checking (in order):
- Custom
USER_RESOLVERcallable (if middleware is installed) MIGRATION_AUDITOR_USERenvironment variableUSER/USERNAME/LOGNAMEenvironment variablesgetpass.getuser()(OS-level username)
🔌 Optional Middleware
If you need to identify the Django user who triggered a migration (e.g. from a custom admin view), add the middleware:
MIDDLEWARE = [
# ...
"migration_auditor.middleware.MigrationAuditorMiddleware",
]
Then configure a USER_RESOLVER:
MIGRATION_AUDITOR = {
"USER_RESOLVER": lambda request: str(request.user) if request.user.is_authenticated else "anonymous",
}
Note: This is only useful in rare setups where migrations run inside a request cycle. For normal
manage.py migrateusage, the middleware is not needed.
📊 Audit Record Fields
| Field | Type | Description |
|---|---|---|
app_label |
CharField | Django app label |
migration_name |
CharField | Migration file name |
direction |
CharField | apply or unapply |
applied_by |
CharField | Who ran the migration |
environment |
CharField | Runtime environment |
hostname |
CharField | Machine hostname |
database_alias |
CharField | Django DB alias |
started_at |
DateTimeField | When it began |
finished_at |
DateTimeField | When it finished |
duration_ms |
IntegerField | Wall-clock time (ms) |
status |
CharField | success, failed, or in_progress |
error_detail |
TextField | Full traceback on failure |
schema_diff |
TextField | Human-readable schema diff |
rollback_sql |
TextField | SQL to reverse the migration |
rollback_script_path |
CharField | Path to saved .sql file |
🧪 Running Tests
pip install -e ".[dev]"
pytest tests/ -v
📋 How It Works
- Signal Interception: On
pre_migrate, the package monkey-patchesMigrationExecutorwithAuditingMigrationExecutor. - Schema Snapshot: Before each migration, a snapshot of the database schema is taken via
connection.introspection. - Migration Execution: The original
apply_migration()/unapply_migration()runs normally. - Post-Execution:
- A second schema snapshot is taken and diffed against the first.
- Rollback SQL is generated via
SchemaEditor(collect_sql=True)— dry-run, nothing is executed. - The rollback SQL is saved to a
.sqlfile. - A
MigrationAuditLogrow is written with all metadata.
- Fail-Safe: All audit operations are wrapped in try/except. If anything goes wrong with recording, the real migration still completes.
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Run tests (
pytest tests/ -v) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License — see the LICENSE file for details.
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 django_migration_auditor-0.1.0.tar.gz.
File metadata
- Download URL: django_migration_auditor-0.1.0.tar.gz
- Upload date:
- Size: 23.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33e57040789dc9270e0a4ad0b3b96fed4eb8a02d72a9970f4ea4d813b75674a6
|
|
| MD5 |
eaa5b0f0b731a86df1141cd25b72b511
|
|
| BLAKE2b-256 |
7eb5fd19762fac9ddd54840cf45366af7ac24b127e26334ad0bdcf26f7c77f50
|
File details
Details for the file django_migration_auditor-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_migration_auditor-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
341a06b2dcbc41b59bd2db8d1c1bf555044b7003ece55b663cf5a10e5b988fc0
|
|
| MD5 |
6cd848ad977a4abb76f927811d3400fc
|
|
| BLAKE2b-256 |
dd4ce54d5ad2f243f1dd54192a40a42315e3e5194bbc651d4601e12d9dbe7670
|