Django多应用与多MySQL数据库迁移配置问题求助
Hey there! Let's break down the issues in your setup and fix them step by step, then I'll share a working example for multiple apps and databases to get you on track.
🔍 Key Issues in Your Current Setup
Mismatched App Labels & Database Mapping
- Your actual apps are named
cherry,apple,mango, but your routers referencecoreandmanas app labels. Django uses an app's official name (from itsAppConfig.nameattribute) for routing, so these mismatches mean your migrations don't know where to go. - The
DATABASE_APPS_MAPPINGconfig uses incorrect keys/values (you don't havecoreormanapps) and is unnecessary when using routers properly.
- Your actual apps are named
Invalid Database Names
- In your
DATABASESsetup,coreandmanhaveNAME: ' DB2'andNAME: ' DB3'(note the leading space). MySQL won't recognize these as valid database names—remove those spaces immediately.
- In your
Router Path & Naming Problems
- Python module paths are case-sensitive, and standard practice uses lowercase for directories/files (you have
Routersinstead ofrouters). - Router class names should follow PascalCase convention (e.g.,
AppleRouterinstead ofcore_router) for readability, and your current path references don't align with your app structure. - You didn't add a router for your
cherryapp, so its models default to thedefaultdatabase (which is what you want for DB1, but explicit routing makes your setup clearer).
- Python module paths are case-sensitive, and standard practice uses lowercase for directories/files (you have
Ambiguous Migration Logic
- Your
allow_migratemethods returnNonefor non-matching apps/databases, which can lead to unpredictable migration behavior. ReturningFalseexplicitly prevents migrations from being applied to the wrong database.
- Your
✅ Working Example for 3 Apps & 3 Databases
Let's rebuild the setup correctly, starting with settings.py:
Updated settings.py
INSTALLED_APPS = [ # Keep default Django apps here (like 'django.contrib.admin', etc.) 'cherry', 'apple', 'mango', ] # Router paths must match your actual file structure DATABASE_ROUTERS = [ 'cherry.routers.CherryRouter', 'apple.routers.AppleRouter', 'mango.routers.MangoRouter', ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost', 'PORT': '3306', 'NAME': 'DB1', 'USER': 'root', 'PASSWORD': 'root', 'OPTIONS': { 'autocommit': True, }, }, 'apple_db': { # Renamed for clarity (matches app purpose) 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost', 'PORT': '3306', 'NAME': 'DB2', # No leading space! 'USER': 'root', 'PASSWORD': 'root', 'OPTIONS': { 'autocommit': True, }, }, 'mango_db': { # Renamed for clarity 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost', 'PORT': '3306', 'NAME': 'DB3', # No leading space! 'USER': 'root', 'PASSWORD': 'root', 'OPTIONS': { 'autocommit': True, }, }, }
Router Files (One Per App)
Create a routers directory inside each app (don't forget to add an __init__.py file in the directory to make it a Python module). Here's what each router looks like:
apple/routers/apple_router.py
class AppleRouter: # Match the app's official name from apple/apps.py route_app_labels = {'apple'} # Map to the database name defined in settings.py target_db = 'apple_db' def db_for_read(self, model, **hints): if model._meta.app_label in self.route_app_labels: return self.target_db return None def db_for_write(self, model, **hints): if model._meta.app_label in self.route_app_labels: return self.target_db return None def allow_relation(self, obj1, obj2, **hints): # Allow relations within the apple app if ( obj1._meta.app_label in self.route_app_labels or obj2._meta.app_label in self.route_app_labels ): return True return None def allow_migrate(self, db, app_label, model_name=None, **hints): # Only allow apple migrations on apple_db if app_label in self.route_app_labels: return db == self.target_db # Block non-apple migrations on apple_db if db == self.target_db: return False return None
mango/routers/mango_router.py
class MangoRouter: route_app_labels = {'mango'} target_db = 'mango_db' def db_for_read(self, model, **hints): if model._meta.app_label in self.route_app_labels: return self.target_db return None def db_for_write(self, model, **hints): if model._meta.app_label in self.route_app_labels: return self.target_db return None def allow_relation(self, obj1, obj2, **hints): if ( obj1._meta.app_label in self.route_app_labels or obj2._meta.app_label in self.route_app_labels ): return True return None def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label in self.route_app_labels: return db == self.target_db if db == self.target_db: return False return None
cherry/routers/cherry_router.py (Optional but Explicit)
class CherryRouter: route_app_labels = {'cherry'} target_db = 'default' # Maps to DB1 def db_for_read(self, model, **hints): if model._meta.app_label in self.route_app_labels: return self.target_db return None def db_for_write(self, model, **hints): if model._meta.app_label in self.route_app_labels: return self.target_db return None def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label in self.route_app_labels: return db == self.target_db if db == self.target_db: return False return None
How to Run Migrations
To migrate each app to its respective database, use the --database flag:
# Migrate cherry to default (DB1) python manage.py makemigrations cherry python manage.py migrate --database=default # Migrate apple to apple_db (DB2) python manage.py makemigrations apple python manage.py migrate --database=apple_db # Migrate mango to mango_db (DB3) python manage.py makemigrations mango python manage.py migrate --database=mango_db
📝 Quick Tips
- Double-check each app's
apps.pyto ensurenamematches the app label (e.g.,apple/apps.pyshould havename = 'apple'). - Test migrations first with
--dry-runto avoid mistakes:python manage.py migrate --database=apple_db --dry-run - If you skip the
CherryRouter, its models will automatically use thedefaultdatabase, but explicit routing makes your setup easier to maintain long-term.
内容的提问来源于stack exchange,提问作者SSS
相关产品推荐
相关产品推荐

