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

Django多数据库路由问题:自定义模型未同步至数据库

多数据库路由下自定义模型未同步至对应数据库问题排查

尝试使用Django数据库路由实现多数据库功能,但自定义模型未同步至对应数据库,仅Django自带模型存在,自定义表未生成。

相关代码文件

models.py

from django.db import models
from django.contrib.auth.models import User

# 多余导入peewee和psycopg2已移除
# Create your models here.
class temp(models.Model):
    id= models.IntegerField(primary_key=True) 
    class Meta:
        app_label='client_db'  # 此处错误:app_label应为应用名称而非数据库别名
        db_table='temp'

class temp2(models.Model):
    id= models.IntegerField(primary_key=True) 
    class Meta:
        app_label='default'  # 此处错误:app_label应为应用名称而非数据库别名
        db_table='temp2'

settings.py

DATABASE_ROUTERS = ('app_celery.dbrouter.client_router',)
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'client_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'amm',
        'USER': 'xxxx',
        'PASSWORD': 'xxxx',
        'HOST': '127.0.0.1',
        'PORT': 5432,
    },
}

dbrouter.py

class client_router:
    """
    A router to control all database operations on models in the
    user application.
    """
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'client_db':
            return 'client_db'
        return 'default'

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'client_db':
            return 'client_db'
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'client_db' or \
           obj2._meta.app_label == 'client_db':
           return True
        return False

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label == 'client_db':
            return db == 'client_db'
        return False  # 此处错误:阻止了所有非client_db应用的迁移,包括自定义应用和Django自带应用的正常迁移

已执行的迁移命令

python3 manage.py makemigrations     
python3 manage.py migrate
python3 manage.py migrate --database=client_db

问题排查与解决方案

1. 修正模型的app_label配置

app_label指定的是模型所属的Django应用名称(比如你的应用是app_celery),而非数据库别名。修改models.py中的Meta类:

class temp(models.Model):
    id= models.IntegerField(primary_key=True) 
    class Meta:
        app_label='app_celery'  # 改为实际应用名称
        db_table='temp'

class temp2(models.Model):
    id= models.IntegerField(primary_key=True) 
    class Meta:
        app_label='app_celery'  # 改为实际应用名称
        db_table='temp2'

2. 修正路由的allow_migrate方法逻辑

当前方法阻止了非client_db应用的所有迁移,导致自定义模型和部分Django自带模型无法正常迁移。修改为按模型或应用规则分配:

def allow_migrate(self, db, app_label, model_name=None, **hints):
    # 处理自定义应用的模型路由
    if app_label == 'app_celery':
        model = hints.get('model')
        # 根据模型表名分配数据库
        if model and model._meta.db_table == 'temp':
            return db == 'client_db'
        elif model and model._meta.db_table == 'temp2':
            return db == 'default'
        return False
    # 允许Django自带核心应用在default数据库迁移
    if app_label in ['auth', 'admin', 'contenttypes', 'sessions']:
        return db == 'default'
    # 其他应用默认不允许迁移
    return False

3. 修正迁移命令执行方式

必须指定应用名称生成迁移文件,否则可能无法识别自定义模型:

# 生成自定义应用的迁移文件
python3 manage.py makemigrations app_celery
# 将temp2模型迁移到default数据库
python3 manage.py migrate app_celery --database=default
# 将temp模型迁移到client_db数据库
python3 manage.py migrate app_celery --database=client_db

4. 清理无关导入

移除models.py中与Django模型无关的导入:from peewee import *和import psycopg2,避免潜在冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:40:24