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-makemigrationsFeatures
- ✅ 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 successfullyWhen to Use
Production deployments:
# CI/CD pipeline
python manage.py migrate_allDocker entrypoint:
CMD python manage.py migrate_all && gunicornmigrator (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 tradingInteractive 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
ExitAuto 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 successfullyMigration Flow
- Creates migrations - Runs
makemigrationsfor all apps - Migrates default database - Migrates main database first
- Migrates routed databases - Migrates blog_db, shop_db based on routing rules
- Migrates constance - Always migrates constance app (required by django-cfg)
When to Use
Development:
# Quick migration during development
python manage.py migrator --autoTesting specific database:
# Test trading database migrations only
python manage.py migrator --database trading_dbTroubleshooting:
# Interactive mode to explore database status
python manage.py migrator
# Select "Show database status" from menuComparison
| Feature | migrate_all | migrator --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 for | Production, CI/CD | Development, 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 0001Migration Strategies
Initial Setup
# 1. Create migrations
python manage.py makemigrations
# 2. Migrate all databases
python manage.py migrate_all
# 3. Verify
python manage.py showmigrationsAdding 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_dbProduction Deployment
# Pre-deployment check
python manage.py migrate_all --dry-run
# Deploy migrations
python manage.py migrate_all
# Verify
python manage.py showmigrationsRouting 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_dbonly - Wallet app migrations → run on
wallet_dbonly - Other apps → run on
defaultdatabase
Migration Storage
Migrations are tracked in the django_migrations table in each database:
# Check migrations on specific database
python manage.py dbshell --database=trading_dbSELECT * FROM django_migrations WHERE app = 'trading';Troubleshooting
Migration Already Applied
# Fake the migration
python manage.py migrate --fake trading 0001 --database=trading_dbMigration Conflicts
# Check for conflicts
python manage.py makemigrations --check
# Merge migrations
python manage.py makemigrations --mergeReset 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-initialCross-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
)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 successfullyNo 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:
- Install Extensions - Ensures PostgreSQL extensions are installed first
- Check Consistency - Detects inconsistent migration history
- Auto-Fix - Removes problematic migration records
- Migrate with Bypass - Applies migrations with consistency check bypass
- 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 migrateBypass 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 automatically2. Manual Test DB Management:
python manage.py test_db reset
# Recreates database and fixes migrations3. Programmatic Usage:
manager.migrate_test_database('default', auto_fix=True)
# Explicitly enables auto-fixDebugging 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_dbCheck 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_all3. Use —fake-initial for existing databases:
# For databases with existing tables
python manage.py migrate --fake-initial4. 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 exist2. Test Migrations Locally
# Test before production
python manage.py migrate_all --dry-run3. Use migrate_all in CI/CD
# .github/workflows/deploy.yml
- name: Run migrations
run: python manage.py migrate_all4. Keep Migration History Clean
# Squash migrations periodically
python manage.py squashmigrations trading 0001 0010See Also
- Core Commands - migrate_all documentation
- Core Commands - migrator documentation
- Routing - Database routing details
- Multi-Database - Multi-database setup