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

Django多库分片场景下迁移失败及只读库配置问题求助

问题解决方案

问题根源分析

  1. migrate无响应:当前路由的allow_migrate方法对非tracking应用返回None,Django默认会尝试在default数据库执行这些迁移,但你要求default数据库只读且原有迁移已完成;同时tracking应用的迁移未明确指定目标库,导致未被执行。
  2. 指定database_tracking迁移报错:Django尝试在database_tracking中执行系统应用(如django.contrib.contenttypes)的迁移,但该数据库未初始化这些系统表,因此出现django_content_type不存在的错误。

具体解决步骤

1. 修正数据库路由规则

更新TrackingRouter的allow_migrate方法,明确各应用的迁移权限:

class TrackingRouter:
    route_app_labels = {'tracking'}
    # 系统应用列表,禁止在database_tracking执行迁移
    system_app_labels = {'django.contrib.admin', 'django.contrib.auth', 
                         'django.contrib.contenttypes', 'django.contrib.sessions', 
                         'django.contrib.messages', 'django.contrib.staticfiles',
                         'django.contrib.postgres'}
    # 禁止迁移的自定义应用(authentication模型为非托管)
    no_migrate_apps = {'authentication'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'database_tracking'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'database_tracking'
        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):
        # 禁止authentication应用的任何迁移操作
        if app_label in self.no_migrate_apps:
            return False
        # tracking应用仅允许在database_tracking执行迁移
        if app_label in self.route_app_labels:
            return db == 'database_tracking'
        # 系统应用禁止在任何数据库执行迁移(原有应用已完成default库的系统表初始化)
        if app_label in self.system_app_labels:
            return False
        # 其他应用默认禁止迁移
        return False

2. 生成并执行tracking应用的迁移

首先确保tracking应用已生成迁移文件:

python manage.py makemigrations tracking

然后仅针对database_tracking执行tracking应用的迁移(避免触发系统应用迁移):

python manage.py migrate tracking --database database_tracking

3. 排除authentication应用的迁移

由于authentication.User设置了managed=False,需避免为其生成迁移:

  • 删除已生成的authentication应用迁移文件(如果有)
  • 后续执行makemigrations时排除该应用:
python manage.py makemigrations --exclude authentication

4. 配置admin面板的用户模型

在authentication/admin.py中注册User模型,确保admin能正常读取default库的用户数据:

from django.contrib import admin
from .models import User

admin.site.register(User)

5. 加固default数据库的只读权限

从数据库层面设置只读用户,彻底避免误操作:
针对MySQL执行以下SQL:

CREATE USER 'readonly_user'@'%' IDENTIFIED BY 'your_secure_password';
GRANT SELECT ON your_default_db_name.* TO 'readonly_user'@'%';
FLUSH PRIVILEGES;

然后在settings.py的DATABASES['default']中使用该只读用户的 credentials。


验证流程

  1. 执行python manage.py migrate tracking --database database_tracking,确认无错误,且database_tracking中生成了tracking应用的表
  2. 启动Django服务,尝试登录admin,确认能使用原有用户正常登录
  3. 测试tracking应用的读写功能,确认操作均指向database_tracking

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:50:07