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

Django自定义User模型与多数据库配置异常排查求助

Django多数据库配置下Admin日志外键约束异常排查与解决

问题核心

自定义认证应用authentication,配置双数据库:auth_db负责auth、contenttypes、authentication应用数据,主库负责其余业务应用。已完成auth_db的模型迁移,通过--database=auth_db创建超级用户并成功登录后台,但在后台创建业务对象时抛出IntegrityError:django_admin_log表外键约束违规,提示user_id=1不存在于authentication_user表中。


排查与解决步骤

1. 检查数据库路由是否覆盖admin应用

django_admin_log属于django.contrib.admin应用,若路由规则未将其指向auth_db,admin日志会默认写入主库,而主库中不存在authentication_user表的对应数据,直接触发外键错误。

打开databases_router.py,确认route_app_labels包含admin:

class AuthRouter:
    # 必须将'admin'加入路由标签列表
    route_app_labels = {'auth', 'contenttypes', 'authentication', 'admin'}

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

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'auth_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 == 'auth_db'
        return db == 'default'  # 主库标识,需与settings.py中一致

2. 验证admin应用的迁移归属

执行命令检查django.contrib.admin的迁移是否在auth_db中完成:

# 查看auth_db中admin的迁移状态
python manage.py showmigrations admin --database=auth_db
# 查看主库中admin的迁移状态
python manage.py showmigrations admin --database=default

如果主库存在admin的迁移记录,先回滚:

python manage.py migrate admin zero --database=default

再在auth_db中执行admin迁移:

python manage.py migrate admin --database=auth_db

3. 排查Celery进程的数据库配置

Celery Beat/Worker若未正确加载Django配置,可能跳过路由规则直接使用默认数据库:

  • 确认Celery启动命令正确指定settings:
    celery -A 你的项目名 beat -l info --settings=你的项目名.settings
    
  • 在Celery任务中添加日志验证数据库路由:
    from django.db import connections
    from celery import shared_task
    import logging
    
    logger = logging.getLogger(__name__)
    
    @shared_task
    def check_db_route():
        from django.contrib.admin.models import LogEntry
        from authentication.models import User
        # 打印LogEntry和User模型使用的数据库
        logger.info(f"LogEntry 数据库: {connections[LogEntry.objects.db].settings_dict['NAME']}")
        logger.info(f"User 模型数据库: {connections[User.objects.db].settings_dict['NAME']}")
    
    执行任务后,若日志显示使用主库,说明Celery未正确应用路由规则,需检查启动环境变量或配置文件加载逻辑。

4. 验证请求上下文的数据库路由

在admin视图中临时添加调试代码,确认当前请求的数据库指向:

# 在任意业务模型的admin.py中添加
from django.contrib.admin.models import LogEntry
from django.db import connections

class YourModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        # 打印LogEntry和当前用户的数据库
        print(f"LogEntry 写入数据库: {connections[LogEntry.objects.db].settings_dict['NAME']}")
        print(f"当前用户所在数据库: {request.user._state.db}")
        super().save_model(request, obj, form, change)

若输出显示LogEntry使用主库,检查settings.py中DATABASE_ROUTERS配置是否正确:

DATABASE_ROUTERS = ['你的项目名.databases_router.AuthRouter']

确保路由类路径无拼写错误。

5. 确认用户数据的数据库归属

在Django Shell中验证当前用户是否来自auth_db:

python manage.py shell

执行代码:

from authentication.models import User
user = User.objects.get(id=1)
print(user._state.db)  # 应输出'auth_db'

若输出非auth_db,检查路由类的db_for_read方法是否正确处理authentication应用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:55:17