{"id":4511,"library":"django-migration-linter","title":"Django Migration Linter","description":"django-migration-linter is a tool for Django projects designed to detect backward incompatible database migrations. It analyzes new migrations against a baseline (e.g., a Git branch) to prevent accidental breaking changes to your database schema. The current version is 6.0.0, and it maintains an active release cadence, frequently adding support for new Python and Django versions.","status":"active","version":"6.0.0","language":"python","source_language":"en","source_url":"https://github.com/3YOURMIND/django-migration-linter","tags":["django","migrations","linter","database","ci","schema","orm"],"install":[{"cmd":"pip install django-migration-linter","lang":"bash","label":"Install via pip"}],"dependencies":[{"reason":"Core functionality is built upon Django's ORM and migration system.","package":"Django","optional":false},{"reason":"Used for comparing migrations against a Git commit or branch. It is an optional dependency if not using git-based comparisons.","package":"GitPython","optional":true}],"imports":[],"quickstart":{"code":"# 1. Add 'django_migration_linter' to your INSTALLED_APPS in settings.py:\n#    INSTALLED_APPS = [\n#        ...,\n#        'django_migration_linter',\n#    ]\n\n# 2. Run the linter as a Django management command.\n#    This example compares new migrations against the 'main' Git branch\n#    and treats any linter warnings as errors (failing the check).\nimport subprocess\nimport os\n\n# Ensure your Django settings are configured for manage.py\n# (e.g., DJANGO_SETTINGS_MODULE environment variable)\n\ntry:\n    print(\"Running django-migration-linter...\")\n    subprocess.check_call([\n        \"python\", \"manage.py\", \"lintmigrations\",\n        \"--git-commit-id\", \"main\",\n        \"--warnings-as-errors\"\n    ])\n    print(\"\\nMigrations linted successfully with no backward incompatible changes detected.\")\nexcept subprocess.CalledProcessError as e:\n    print(f\"\\nMigration linter failed with exit code {e.returncode}:\")\n    print(\"Please review the output for backward incompatible changes and fix them.\")\nexcept FileNotFoundError:\n    print(\"Error: 'python' command not found. Ensure Python is in your PATH and manage.py exists.\")\n","lang":"python","description":"To quickly use `django-migration-linter`, add it to your `INSTALLED_APPS` and then execute the `lintmigrations` management command. The example demonstrates how to run the linter to compare migrations in your current branch against the 'main' branch, ensuring that any detected warnings will cause the command to fail. This is typically run in CI/CD pipelines."},"warnings":[{"fix":"No direct code change is typically needed unless your specific setup or scripts relied on the old behavior for custom-labeled apps. Ensure your `django_migration_linter` configuration and expectations align with app labels.","message":"As of v6.0.0, `django-migration-linter` now correctly handles custom Django app labels when determining migrations from a Git reference. Previously, it might have relied on folder names. If your project uses custom app labels, the linter will now reference apps by their Django label, which might change detection behavior if you were implicitly relying on folder names.","severity":"breaking","affected_versions":">=6.0.0"},{"fix":"Ensure your environment (e.g., CI/CD) provides a correctly configured and accessible database for `sqlmigrate` to run successfully. Address any underlying issues causing `sqlmigrate` errors. If an error is truly ignorable (rare), you can use the `--ignore-sqlmigrate-errors` option (available from v5.1.0 and later).","message":"Beginning with v5.0.0, the linter no longer silently ignores failures that occur during its internal calls to Django's `sqlmigrate` command. Instead, it will now crash and raise the `sqlmigrate` error. This change prevents problematic migrations from passing the linter unnoticed, especially if SQL generation requires specific database conditions.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Update any scripts or CI/CD configurations that invoke `manage.py lintmigrations` to use the new argument syntax, for example: `manage.py lintmigrations --git-commit-id <commit_id>`.","message":"In v3.0.0, the command-line interface for `lintmigrations` underwent a breaking change. The `GIT_COMMIT_ID` positional argument became an optional named argument (`--git-commit-id [GIT_COMMIT_ID]`), and the command now accepts `[app_label]` and `[migration_name]` as new positional arguments.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure your environment where `lintmigrations` is run (e.g., local development, CI/CD pipeline) has a valid database connection configured in Django settings. You can use a lightweight database like SQLite for testing purposes if full database functionality isn't strictly needed for the SQL analysis.","message":"The linter's deep analysis often depends on Django's `sqlmigrate` command, which typically requires an active database connection to generate and inspect the SQL for migration files. Running the linter in an environment without a configured or accessible database can lead to `sqlmigrate` failures, which will crash the linter (since v5.0.0).","severity":"gotcha","affected_versions":"all"},{"fix":"Always consult the specific release notes for the `django-migration-linter` version you intend to use to confirm compatibility with your project's Python and Django versions. Upgrade your Python/Django stack if it falls outside the supported range for the desired linter version.","message":"Numerous releases have dropped support for older Python and Django versions. For instance, Python 3.7 and 3.8 were dropped in v5.2.0. Django 1.11, 2.0, 2.1, 3.0, and 3.1 were dropped in v4.0.0, alongside Python 2.7, 3.5, and 3.6.","severity":"breaking","affected_versions":">=4.0.0"}],"env_vars":null,"search_vec":"'6.0.0':45 'accident':34 'activ':50 'ad':54 'analyz':22 'backward':17 'baselin':27 'branch':31 'break':35 'cadenc':52 'chang':36 'ci':66 'current':42 'databas':19,39,65 'design':14 'detect':16 'django':1,5,12,60,62 'django-migration-lint':4 'e.g':28 'frequent':53 'git':30 'incompat':18 'linter':3,7,64 'maintain':48 'migrat':2,6,20,24,63 'new':23,57 'orm':68 'prevent':33 'project':13 'python':58 'releas':51 'schema':40,67 'support':55 'tool':10 'version':43,61","created_at":"2026-04-12T13:55:47.224426+00:00","updated_at":"2026-04-16T14:32:14.780508+00:00","problems":[{"fix":"To resolve this, make the column nullable initially, set a database-level default (e.g., using Django 5.0's `db_default`), or populate existing rows with a default value using `RunPython` before making the column non-nullable in a separate migration step.","cause":"This error occurs when a migration attempts to add a non-nullable column to an existing table without providing a default value.","error":"ERR NOT NULL constraint on columns"},{"fix":"Implement a multi-step deployment: first, remove all application code references to the table, deploy, and only in a subsequent deployment, create a migration to drop the table.","cause":"This error indicates a backward-incompatible operation where a migration attempts to drop a database table that might still be accessed by older versions of your application code during deployment.","error":"ERR DROPPING table"},{"fix":"Perform a multi-step table rename: first, create a new table with the desired name, migrate data from the old to the new table, update application code to use the new table, and only then drop the old table in a later deployment.","cause":"This error is raised when a migration renames a database table, which can break application code that expects the original table name, especially in blue/green or rolling deployments.","error":"ERR RENAMING tables"},{"fix":"Replace direct model imports with `MyModel = apps.get_model('app_label', 'MyModel')` to ensure the migration operates on the historical model state at that point in the migration history.","cause":"This warning/error occurs in `RunPython` operations when Django models are directly imported (e.g., `from myapp.models import MyModel`) instead of using `apps.get_model()`, which can lead to using the incorrect (latest) schema of the model during migration execution.","error":"'forwards_func': Could not find an 'apps.get_model(\"...\")' call. Importing the model directly is incorrect for data migrations."}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"django-migration-linter","cli_version":"sh: 1: django-migration-linter: not found","type":"library","homepage":null,"github":"https://github.com/3YOURMIND/django-migration-linter","docs":null,"changelog":"https://github.com/3YOURMIND/django-migration-linter/blob/main/CHANGELOG.md","pypi":"https://pypi.org/project/django-migration-linter/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["database","testing","web-framework"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-04-12","next_check":"2026-07-11","install_tag":null}}