Skip to Content
DatabaseMigrations

Multi-Database Migrations

Django-CFG provides two powerful commands for managing multi-database migrations.

migrate_all (Production)

Automatically migrates all databases based on routing configuration.

Usage

# Migrate all databases python manage.py migrate_all # Skip automatic makemigrations python manage.py migrate_all --skip-makemigrations

Features

  • ✅ Auto-detects all databases from settings
  • ✅ Creates migrations first (unless —skip-makemigrations)
  • ✅ Migrates each database based on routing rules
  • ✅ Handles constance app automatically
  • ✅ Shows success/failure for each database

Example Output

$ python manage.py migrate_all 🚀 Migrating all databases... 🔄 Migrating database: default 📦 Migrating all apps... Migrations completed for default 🔄 Migrating database: trading_db 📦 Migrating app: trading Migrations completed for trading_db 🔄 Migrating database: wallet_db 📦 Migrating app: wallet Migrations completed for wallet_db All migrations completed successfully

When to Use

Production deployments:

# CI/CD pipeline python manage.py migrate_all

Docker entrypoint:

CMD python manage.py migrate_all && gunicorn

migrator (Development)

Interactive migration tool with auto mode and targeted migrations.

Usage

# Auto mode - migrates all databases without prompts python manage.py migrator --auto # Interactive mode - shows menu python manage.py migrator # Migrate specific database python manage.py migrator --database trading_db # Migrate specific app python manage.py migrator --app trading # Migrate specific app on specific database python manage.py migrator --database trading_db --app trading

Interactive Mode

When run without --auto, shows an interactive menu:

🗄️ Django Database Migrator ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📋 Current Configuration: Databases: default, trading_db, wallet_db Apps: accounts, trading, wallet, analytics What would you like to do? > Migrate all databases (recommended) Migrate specific database Show database status View configuration info Exit

Auto Mode

Runs automatic migration without prompts:

$ python manage.py migrator --auto 🚀 Running automatic migration... 📦 Creating migrations for all apps... Migrations created successfully 🔄 Migrating database: default 📦 Migrating all apps... Migrations completed for default 🔄 Migrating database: trading_db 📦 Migrating app: trading Migrations completed for trading_db 🔄 Migrating database: wallet_db 📦 Migrating app: wallet Migrations completed for wallet_db Constance migrated successfully

Migration Flow

  1. Creates migrations - Runs makemigrations for all apps
  2. Migrates default database - Migrates main database first
  3. Migrates routed databases - Migrates blog_db, shop_db based on routing rules
  4. Migrates constance - Always migrates constance app (required by django-cfg)

When to Use

Development:

# Quick migration during development python manage.py migrator --auto

Testing specific database:

# Test trading database migrations only python manage.py migrator --database trading_db

Troubleshooting:

# Interactive mode to explore database status python manage.py migrator # Select "Show database status" from menu

Comparison

Featuremigrate_allmigrator --auto
Interactive menu❌ No✅ Yes (without —auto)
Auto makemigrations✅ Yes (unless —skip-makemigrations)✅ Yes
Respects routing rules✅ Yes✅ Yes
Specific database❌ Migrates all✅ —database flag
Specific app❌ Migrates all apps✅ —app flag
Constance handling✅ Automatic✅ Automatic
Best forProduction, CI/CDDevelopment, targeted migrations

Standard Django Migrations

You can still use standard Django migration commands:

# Create migrations python manage.py makemigrations python manage.py makemigrations trading # Migrate specific database python manage.py migrate --database=trading_db python manage.py migrate trading --database=trading_db # Migrate all databases (respects routing) python manage.py migrate # Show migration status python manage.py showmigrations python manage.py showmigrations --database=trading_db # Fake migration python manage.py migrate --fake trading_db # Rollback migration python manage.py migrate trading 0001

Migration Strategies

Initial Setup

# 1. Create migrations python manage.py makemigrations # 2. Migrate all databases python manage.py migrate_all # 3. Verify python manage.py showmigrations

Adding New Model

# 1. Add model to apps/trading/models.py # 2. Create migration python manage.py makemigrations trading # 3. Migrate trading database only python manage.py migrator --database trading_db

Production Deployment

# Pre-deployment check python manage.py migrate_all --dry-run # Deploy migrations python manage.py migrate_all # Verify python manage.py showmigrations

Routing and Migrations

How Routing Affects Migrations

# settings.py DATABASE_ROUTING_RULES = { 'trading': 'trading_db', 'wallet': 'wallet_db', }

Migration behavior:

  • Trading app migrations → run on trading_db only
  • Wallet app migrations → run on wallet_db only
  • Other apps → run on default database

Migration Storage

Migrations are tracked in the django_migrations table in each database:

# Check migrations on specific database python manage.py dbshell --database=trading_db
SELECT * FROM django_migrations WHERE app = 'trading';

Troubleshooting

Migration Already Applied

# Fake the migration python manage.py migrate --fake trading 0001 --database=trading_db

Migration Conflicts

# Check for conflicts python manage.py makemigrations --check # Merge migrations python manage.py makemigrations --merge

Reset Migrations (Development Only)

# Delete migration files (keep __init__.py) find . -path "*/migrations/*.py" -not -name "__init__.py" -delete find . -path "*/migrations/*.pyc" -delete # Drop and recreate databases python manage.py migrate_all --fake-initial

Cross-Database Migration Errors

If you get relation does not exist errors:

# models.py - Add db_constraint=False for cross-database ForeignKeys author = models.ForeignKey( User, on_delete=models.CASCADE, db_constraint=False # REQUIRED for cross-database FK )

See: Cross-Database Relations

Migration Auto-Fix

Django-CFG includes intelligent migration management that automatically detects and fixes common migration issues.

Automatic Inconsistency Detection

The MigrationManager automatically detects migration inconsistencies:

from django_cfg.management.utils.migration_manager import MigrationManager manager = MigrationManager() # Check for migration consistency issues has_issues = manager.check_migration_consistency('default') if has_issues: print("Found inconsistent migration history")

Django-CFG CustomUser Standard

Built-in Configuration:

Django-CFG automatically configures CustomUser as a core feature:

# Auto-configured in core/generation/core_generators/settings.py (line 75): AUTH_USER_MODEL = "django_cfg_accounts.CustomUser" # App configuration in apps.py: # name = "django_cfg.apps.system.accounts" # label = "django_cfg_accounts" # This is the app label used everywhere # No manual setup needed - works out of the box!

Automatic Migration Order Fix:

SmartTestRunner automatically handles migration order issues:

# During test database setup: # 1. Detects inconsistent migration history # 2. Removes problematic migration records # 3. Reapplies migrations in correct dependency order # 4. Tests run successfully # For production/manual use: manager.fix_inconsistent_migrations('default')

Note: CustomUser (django_cfg_accounts.CustomUser) is automatically configured by django-cfg - no manual AUTH_USER_MODEL setup needed!

Test Database Auto-Fix

During testing, SmartTestRunner automatically handles migration issues:

$ python manage.py test Creating test database for alias 'default'... ⚠️ Using smart migration manager to fix: InconsistentMigrationHistory Migrations applied successfully

No manual intervention needed - tests just work!

Manual Fix for Production

For production databases, use MigrationManager programmatically:

from django_cfg.management.utils.migration_manager import MigrationManager # Initialize manager manager = MigrationManager( stdout=sys.stdout, style=self.style, logger=logger ) # Migrate test database with auto-fix manager.migrate_test_database('default', auto_fix=True)

What it does:

  1. Install Extensions - Ensures PostgreSQL extensions are installed first
  2. Check Consistency - Detects inconsistent migration history
  3. Auto-Fix - Removes problematic migration records
  4. Migrate with Bypass - Applies migrations with consistency check bypass
  5. Verify - Confirms successful migration

Fix Specific Issues

Remove problematic migration records:

# Example: Fix admin migrations applied before custom user from django.db.migrations.recorder import MigrationRecorder from django.db import connections connection = connections['default'] recorder = MigrationRecorder(connection) # Remove admin migrations (will be reapplied correctly) recorder.migration_qs.filter(app='admin').delete() # Run migrations again python manage.py migrate

Bypass consistency check temporarily:

from django_cfg.management.utils.migration_manager import MigrationManager manager = MigrationManager() # Migrate with consistency check bypass manager._migrate_with_bypass('default')

When Auto-Fix Runs

Auto-fix is triggered in these scenarios:

1. Test Database Creation:

python manage.py test # Auto-fixes migration issues automatically

2. Manual Test DB Management:

python manage.py test_db reset # Recreates database and fixes migrations

3. Programmatic Usage:

manager.migrate_test_database('default', auto_fix=True) # Explicitly enables auto-fix

Debugging Migration Issues

Check migration status:

# Show all migrations python manage.py showmigrations # Show specific app python manage.py showmigrations accounts # Show for specific database python manage.py showmigrations --database blog_db

Check migration records in database:

-- PostgreSQL SELECT app, name, applied FROM django_migrations ORDER BY id; -- Check if admin is before accounts SELECT (SELECT MIN(id) FROM django_migrations WHERE app = 'admin') as admin_min, (SELECT MIN(id) FROM django_migrations WHERE app = 'accounts') as accounts_min;

Check migration dependencies:

from django.db.migrations.loader import MigrationLoader from django.db import connections loader = MigrationLoader(connections['default']) # Get migration migration = loader.get_migration('admin', '0001_initial') # Check dependencies print(migration.dependencies) # [('auth', '0011_update_proxy_permissions'), ('accounts', '0001_initial')]

Advanced Auto-Fix Configuration

Customize auto-fix behavior:

from django_cfg.management.utils.migration_manager import MigrationManager class CustomMigrationManager(MigrationManager): def fix_inconsistent_migrations(self, db_name: str): """Custom fix logic.""" super().fix_inconsistent_migrations(db_name) # Additional custom fixes self._fix_custom_app_migrations(db_name) def _fix_custom_app_migrations(self, db_name: str): """Fix custom app specific issues.""" from django.db.migrations.recorder import MigrationRecorder from django.db import connections recorder = MigrationRecorder(connections[db_name]) # Remove problematic migrations for custom app recorder.migration_qs.filter(app='my_custom_app').delete() self._log_success("Fixed custom app migrations")

Prevention Tips

1. Django-CFG handles CustomUser automatically:

# Django-CFG automatically configures: # - AUTH_USER_MODEL = "django_cfg_accounts.CustomUser" # - Adds 'django_cfg.apps.system.accounts' to INSTALLED_APPS # - Sets app label = "django_cfg_accounts" # No manual configuration needed! # This is core django-cfg functionality.

2. Run migrations in order:

# Django-CFG migrations are already created # Just run migrate command: python manage.py migrate # Or use django-cfg commands: python manage.py migrator --auto python manage.py migrate_all

3. Use —fake-initial for existing databases:

# For databases with existing tables python manage.py migrate --fake-initial

4. Keep migration order in version control:

# Commit migrations in order git add apps/accounts/migrations/0001_initial.py git commit -m "Add initial user migration" git add apps/trading/migrations/ git commit -m "Add trading migrations"

See Test Database Management for testing-specific auto-fix features.


Best Practices

1. Always Create Migrations First

# ✅ Good python manage.py makemigrations python manage.py migrate_all # ❌ Bad python manage.py migrate_all # May fail if migrations don't exist

2. Test Migrations Locally

# Test before production python manage.py migrate_all --dry-run

3. Use migrate_all in CI/CD

# .github/workflows/deploy.yml - name: Run migrations run: python manage.py migrate_all

4. Keep Migration History Clean

# Squash migrations periodically python manage.py squashmigrations trading 0001 0010

See Also

Last updated on