Skip to Content
FeaturesModulesMigratorConfiguration

Configuration

django_migrator does not have a Pydantic config block in DjangoConfig — it reads routing from the standard DATABASES setting (populated by django-cfg’s DatabaseConfig.apps field) and receives runtime behavior through MigratorOptions.

MigratorOptions

A frozen dataclass that controls orchestrator behavior for one run.

FieldTypeDefaultDescription
repairboolFalseAllow the orchestrator to auto-repair detected drift. Without this, drift is reported as an error and migration stops.
dry_runboolFalseNo DDL, no record changes — forensic check only. Drift is reported but nothing is fixed or migrated.
interactiveboolTruePrompt before applying repairs. Set to False for CI.
skip_makemigrationsboolFalseSkip the makemigrations step. Faster when you know migrations are already generated.
verbosityint1Passed to underlying migrate and makemigrations calls.
from django_cfg.modules.django_migrator import MigratorOptions options = MigratorOptions( repair=True, dry_run=False, interactive=False, # CI mode skip_makemigrations=True, verbosity=2, )

Database routing

Routing rules come from settings.DATABASE_ROUTING_RULES, which django-cfg generates automatically from each DatabaseConfig.apps field in your project config.

# api/config.py from django_cfg import DjangoConfig, DatabaseConfig class MyConfig(DjangoConfig): databases = { "default": DatabaseConfig.from_url( url="${DATABASE_URL}", ), "vehicles": DatabaseConfig.from_url( url="${DATABASE_URL_VEHICLES}", apps=["catalog", "catalog_api", "normalizer", "intelligence"], test_mirror="default", # only honored when DB NAMEs match (test mode) ), }

Models in apps=[...] route to vehicles; everything else stays in default. The orchestrator never overrides this mapping — it respects whatever allow_migrate returns from the router.

test_mirror="default" is safe. The guard test_mirror_isolation detects when TEST.MIRROR is actively routing writes outside of test mode by comparing physical database NAMEs. If the NAMEs differ (mirror configured but inactive), the guard passes silently.

Command-line flags

The migrate_all management command maps directly to MigratorOptions:

FlagMigratorOptions field
--checkdry_run=True
--repairrepair=True
--non-interactiveinteractive=False
--skip-makemigrationsskip_makemigrations=True
-v Nverbosity=N

Guard configuration

Guards run before each database and are configured in orchestration/guards.py. The default guard set includes:

GuardFatalWhat it detects
connection_liveYesDead connection — bad credentials, unreachable host, typo in alias.
test_mirror_isolationYesTEST.MIRROR actively redirecting writes in non-test mode.
no_concurrent_migrationYesAnother process holds a PostgreSQL advisory migration lock.

Custom guards can be added by appending to DEFAULT_GUARDS or by passing a custom tuple to GuardSet(...).

Processing order

Databases are processed in a deterministic order: default first, then all other aliases alphabetically. This ensures cross-database FK targets exist before routed apps try to reference them.

# Internal ordering in manager.py aliases = ["default"] + sorted(other_aliases)

Report types

migrate_all() returns a MigrationReport aggregate. Inspect it programmatically:

report = migrator.migrate_all() # Top-level status print(report.all_clean) # bool — True if every DB is clean # Per-DB for db in report.db_reports: print(db.alias) print(db.is_clean) # bool print(db.aborted) # bool — guard tripped print(db.errors) # list[str] print(db.warnings) # list[str] print(db.repairs_applied) # list[str] print(db.pending_after_migrate) # int if db.drift: print(db.drift.total_drift_count())

Render as terminal text:

from django_cfg.modules.django_migrator import TextReportFormatter print(TextReportFormatter().render(report))

Output example:

═══ Migration Report ═══ • default — in sync ✅ Executed: migrate --database=default • vehicles — WARNINGS Drift: 0 recorded-missing, 1 unrecorded-present, 0 half-applied - unrecorded_present catalog.0003_vehicle_source_meta (table catalog_vehicle_photo exists in DB) Repairs: ✓ fake-apply vehicles:catalog.0003_vehicle_source_meta Executed: migrate --database=vehicles ✅ All 2 database(s) in sync.
Last updated on