Django "relation does not exist"自定义用户类和 Postgresql 模式的错误



在使用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_groupauth_group_permissionsauth_permissiondjango_admin_logdjango_content_typedjango_session)。

但是,我不确定:

  1. 如果路由器应该像我一样编写(一系列if/elif) -->有没有更好的方法为多个模式编写路由器?
  2. 哪些是对应于 上面列出的 Django 表。--> 通过查看django/contrib目录,我能够猜出最后三个类名(django_admin_logdjango_content_typedjango_session),但是我应该如何找到auth_groupauth_group_permissionsauth_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',
}
}

最新更新