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

Django createsuperuser指定--database仍创建到default库问题求助

Django多数据库下createsuperuser指定数据库无效问题

问题背景

项目配置了3个PostgreSQL数据库:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'default',
        'USER': 'user',
        'PASSWORD': 'password',
    },
    'clients_db': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'clients_db',
        'USER': 'user',
        'PASSWORD': 'password',
    },
    'other': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'other',
        'USER': 'user',
        'PASSWORD': 'password',
    },
}

包含3个应用:clients、users、myapp,其中clients应用配置了专属数据库路由,指定连接clients_db:

class ClientsRouter:

    route_app_labels = {'clients'}

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

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'clients_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 == 'clients_db'
        return None

其余两个应用共享同一数据库,迁移操作均正常:

  • 生成迁移文件:python manage.py makemigrations
  • 应用迁移到default数据库:python manage.py migrate
  • 应用迁移到other数据库:python manage.py migrate --database other

但执行python manage.py createsuperuser --database other时,超级用户仍被创建到default数据库中。

已安装应用列表:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.humanize',
    'clients',
    'users',
    'myapp',
    'django_filters',
    'widget_tweaks',
]

补充:尝试通过shell指定数据库创建超级用户,结果仍创建到default数据库。


问题原因

当前的数据库路由仅处理了clients应用的模型路由,而createsuperuser操作的是django.contrib.auth下的User模型,没有对应的路由规则。当路由的db_for_write方法返回None时,Django会默认使用default数据库,即使命令中指定了--database other。


解决方案

方法1:扩展现有路由,处理内置auth类应用

修改ClientsRouter,添加对auth、admin等内置应用的路由逻辑,使其能识别命令指定的数据库:

class ClientsRouter:

    route_app_labels = {'clients'}
    # 内置核心应用列表,根据实际需要调整
    core_app_labels = {'auth', 'admin', 'contenttypes', 'sessions', 'messages'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'clients_db'
        # 若为核心应用,优先使用hints中传递的数据库
        if model._meta.app_label in self.core_app_labels:
            return hints.get('db')
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'clients_db'
        if model._meta.app_label in self.core_app_labels:
            return hints.get('db')
        return None

    def allow_relation(self, obj1, obj2, **hints):
        # 允许clients应用的关联
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
            return True
        # 允许核心应用的关联
        if (
            obj1._meta.app_label in self.core_app_labels or
            obj2._meta.app_label in self.core_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 == 'clients_db'
        # 允许核心应用在default和other数据库迁移
        if app_label in self.core_app_labels:
            return db in ['default', 'other']
        return None

方法2:指定非clients应用默认路由到other数据库

如果希望users、myapp及内置auth应用默认使用other数据库,可调整路由逻辑:

class ClientsRouter:

    route_app_labels = {'clients'}
    other_app_labels = {'users', 'myapp', 'auth', 'admin', 'contenttypes', 'sessions', 'messages'}

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

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'clients_db'
        if model._meta.app_label in self.other_app_labels:
            return 'other'
        return None

    # allow_relation和allow_migrate方法做对应调整
    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
        if (
            obj1._meta.app_label in self.other_app_labels or
            obj2._meta.app_label in self.other_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 == 'clients_db'
        if app_label in self.other_app_labels:
            return db == 'other'
        return None

方法3:Shell中显式指定数据库创建用户

通过shell创建时,必须使用using()方法指定目标数据库:

from django.contrib.auth.models import User
User.objects.using('other').create_superuser(username='admin', email='admin@example.com', password='your_password')

注意:确保other数据库已完成auth相关应用的迁移(已执行python manage.py migrate --database other即可)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:35:28