在使用Postgresql数据库的Django项目上运行createsuperuser
时,我遇到了一个django.db.utils.ProgrammingError: relation "user" does not exist
错误。
我编写了以下数据库路由器来指示表user
(基于AbstractUser
类的自定义扩展)位于模式users
中。即便如此,Django 也找不到它。
from myapp.models import Class1, Class2, Class3
from users.models import User
from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.models import Session
# Include here classes (i.e. tables) that belongs to the "myapp" schema
ROUTED_MODELS_MYAPP = [Class1, Class2, Class3]
# Include here classes (i.e. tables) that belongs to the "users" schema
ROUTED_MODELS_USERS = [User, LogEntry, ContentType, Session] #classes for custom user model, and django tables `django_admin_log`, `django_content_type`, `django_session` tables
# classes for the following table names still missing from list: `auth_group`, `auth_group_permissions`, `auth_permission`.
class MyDBRouter(object):
"""
A router to place DB queries into correct schema depending on considered tables.
Sources:
https://stackoverflow.com/a/51007441/3976696
https://www.amvtek.com/blog/posts/2014/Jun/13/accessing-multiple-postgres-schemas-from-django/
"""
def db_for_read(self, model, **hints):
if model in ROUTED_MODELS_MYAPP:
return 'myapp'
elif model in ROUTED_MODELS_USERS:
return 'users'
return None
def db_for_write(self, model, **hints):
if model in ROUTED_MODELS_MYAPP:
return 'myapp'
elif model in ROUTED_MODELS_USERS:
return 'users'
return None
路由器适用于与身份验证无关的其他表,所以我怀疑这与 Django 第一次迁移 User 类时自动创建的其他表有关(auth_group
、auth_group_permissions
、auth_permission
、django_admin_log
、django_content_type
、django_session
)。
但是,我不确定:
- 如果路由器应该像我一样编写(一系列
if
/elif
) -->有没有更好的方法为多个模式编写路由器? - 哪些是对应于 上面列出的 Django 表。--> 通过查看
django/contrib
目录,我能够猜出最后三个类名(django_admin_log
、django_content_type
、django_session
),但是我应该如何找到auth_group
、auth_group_permissions
、auth_permission
的类名呢?
编辑:根据@Kevin的评论,我尝试根据app_label
而不是型号名称编写路由器,如文档中所示,为每个涉及的应用程序制作一个路由器。我还尝试在我的用户类的 Meta 类中手动指定app_label
(即app_label = 'users'
)。
但是,当我在createsuperuser
中输入用户名时,原始错误(django.db.utils.ProgrammingError: relation "user" does not exist
)仍然存在。我还应该如何处理路由器中的这种情况?
#Route all models in admin application, cf. https://docs.djangoproject.com/en/2.1/topics/db/multi-db/
class AdminRouter:
"""
A router to control all database operations on models in the admin application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read admin models go to users.
"""
if model._meta.app_label == 'admin':
return 'users'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write admin models go to users.
"""
if model._meta.app_label == 'admin':
return 'users'
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the admin app only appears in the 'users' database.
"""
if app_label == 'admin':
return db == 'users'
return None
class AuthRouter:
"""
A router to control all database operations on models in the
auth application.
"""
<similar to previous router>
class ContentTypeRouter:
"""
A router to control all database operations on models in the
contenttype application.
"""
<similar to previous router>
class SessionRouter:
"""
A router to control all database operations on models in the
sessionapplication.
"""
<similar to previous router>
#Route all models in users application, cf. https://docs.djangoproject.com/en/2.1/topics/db/multi-db/
class UsersRouter:
"""
A router to control all database operations on models in the users application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read user models go to users.
"""
if model._meta.app_label == 'users':
return 'users'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write user models go to users.
"""
if model._meta.app_label == 'users':
return 'users'
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the user app only appears in the 'users' database.
"""
if app_label == 'users':
return db == 'users'
return None
然后,我按以下顺序从settings.py
调用它们:
DATABASE_ROUTERS = (
'urbio.dbrouters.AdminRouter',
'urbio.dbrouters.AuthRouter',
'urbio.dbrouters.ContentTypeRouter',
'urbio.dbrouters.SessionRouter',
'urbio.dbrouters.UsersRouter',
)
解决方案是在运行createsuperuser
命令时指定--database
标志并指向正确的架构:
python manage.py createsuperuser --database users
此外,在此答案之后,settings.py
中的数据库定义是:
DATABASES = {
'default':
{},
'schema1':
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=schema1'
},
'NAME': 'mydbname',
'USER': 'myusername',
'PASSWORD': '***',
'HOST': 'my.host.address',
'PORT': '5432',
},
'users':
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=users'
},
'NAME': 'mydbname',
'USER': 'myusername',
'PASSWORD': '***',
'HOST': 'my.host.address',
'PORT': '5432',
}
}