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
相关产品推荐
相关产品推荐

