You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

  1. Mismatched App Labels & Database Mapping

    • Your actual apps are named cherry, apple, mango, but your routers reference core and man as app labels. Django uses an app's official name (from its AppConfig.name attribute) for routing, so these mismatches mean your migrations don't know where to go.
    • The DATABASE_APPS_MAPPING config uses incorrect keys/values (you don't have core or man apps) and is unnecessary when using routers properly.
  2. Invalid Database Names

    • In your DATABASES setup, core and man have NAME: ' DB2' and NAME: ' DB3' (note the leading space). MySQL won't recognize these as valid database names—remove those spaces immediately.
  3. Router Path & Naming Problems

    • Python module paths are case-sensitive, and standard practice uses lowercase for directories/files (you have Routers instead of routers).
    • Router class names should follow PascalCase convention (e.g., AppleRouter instead of core_router) for readability, and your current path references don't align with your app structure.
    • You didn't add a router for your cherry app, so its models default to the default database (which is what you want for DB1, but explicit routing makes your setup clearer).
  4. Ambiguous Migration Logic

    • Your allow_migrate methods return None for non-matching apps/databases, which can lead to unpredictable migration behavior. Returning False explicitly prevents migrations from being applied to the wrong database.

✅ 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.py to ensure name matches the app label (e.g., apple/apps.py should have name = 'apple').
  • Test migrations first with --dry-run to avoid mistakes: python manage.py migrate --database=apple_db --dry-run
  • If you skip the CherryRouter, its models will automatically use the default database, but explicit routing makes your setup easier to maintain long-term.

内容的提问来源于stack exchange,提问作者SSS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:27:37