Как правильно настроить пользовательскую модель User и несколько баз данных в Django?
Я создал пользовательское приложение для аутентификации пользователей и столкнулся с трудностями, чтобы заставить все работать с несколькими базами данных. Помощь была бы очень признательна.
В принципе, я создаю несколько проектов Django и хочу иметь уникальную базу данных для аутентификации и пользовательскую базу данных AUTH_USER_MODEL
. Базы данных объявлены в settings.py с двумя маршрутизаторами, один для приложения auth
, contenttypes
и authentication
, а другой маршрутизатор для остальных приложений.
Я успешно перенес пользовательскую модель User
и создал createsuperuser
с опцией --database=auth_db
, но затем, когда я работаю в секции администратора и создаю объект в одном из моих приложений, Django выдает ошибку :
IntegrityError at /admin/django_celery_beat/crontabschedule/add/
insert or update on table "django_admin_log" violates foreign key constraint "django_admin_log_user_id_c564eba6_fk_authentication_user_id"
DETAIL: Key (user_id)=(1) is not present in table "authentication_user".
Как вы можете видеть, он говорит, что пользователь с ID 1 не создан, но я вошел в систему и я на 100% уверен, что пользовательская модель User
была создана в приложении authentication
:
root@ec00652b9b9a:/app# python manage.py migrate authentication --database=auth_db
Operations to perform:
Apply all migrations: authentication
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying authentication.0001_initial... OK
root@ec00652b9b9a:/app# python manage.py migrate contenttypes --database=auth_db
Operations to perform:
Apply all migrations: contenttypes
Running migrations:
No migrations to apply.
root@ec00652b9b9a:/app# python manage.py migrate auth --database=auth_db
Operations to perform:
Apply all migrations: auth
Running migrations:
No migrations to apply.
root@ec00652b9b9a:/app# python manage.py migrate admin --database=default
Operations to perform:
Apply all migrations: admin
Running migrations:
Applying admin.0001_initial... OK
root@ec00652b9b9a:/app# python manage.py migrate sessions --database=default
Operations to perform:
Apply all migrations: sessions
Running migrations:
Applying sessions.0001_initial... OK
Значит ли это, что Celery beat
или admin
ищет не в той базе данных? Как я могу исследовать эту проблему дальше?
databases_router.py
class AuthRouter:
route_app_labels = {'auth', 'contenttypes', 'authentication'}
def db_for_write(self, model, **hints):
if model._meta.app_label in self.route_app_labels:
return 'auth_db'
return None
def db_for_read(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 None
class AppsRouter:
def db_for_write(self, model, **hints):
return 'default'
def db_for_read(self, model, **hints):
return 'default'
def allow_relation(self, obj1, obj2, **hints):
return True
def allow_migrate(self, db, app_label, model_name=None, **hints):
return True
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env("PROJECT_DB_NAME"),
'HOST': env("PROJECT_DB_HOST"),
'PORT': env("PROJECT_DB_PORT"),
'USER': env("PROJECT_DB_USER"),
'PASSWORD': env("PROJECT_DB_PASSWORD"),
'OPTIONS': {'sslmode': 'require',
'options': '-c search_path=public'
},
},
'auth_db': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env("AUTHENTICATION_DB_NAME"),
'HOST': env("AUTHENTICATION_DB_HOST"),
'USER': env("AUTHENTICATION_DB_USER"),
'PORT': env("AUTHENTICATION_DB_PORT"),
'PASSWORD': env("AUTHENTICATION_DB_PASSWORD"),
'OPTIONS': {'sslmode': 'require',
'options': '-c search_path=public'
},
},
}
DATABASE_ROUTERS = ['project.databases_router.AuthRouter', 'project.databases_router.AppsRouter']
AUTH_USER_MODEL = 'authentication.User'
Я не уверен насчет последних версий Django, но я не помню, чтобы Django (как и Postgres) мог обрабатывать отношения внешних ключей с другими базами данных (модель Django LogEntry полагается на одну)
Возможно, будет проще опустить админку Django и написать что-то самому, или подправить модель логирования.
Однако я бы пересмотрел ваше требование отделить пользователя от базы данных по умолчанию. Если вы действительно отделяете пользователя от контекстного приложения, вам, вероятно, не стоит полагаться на какие-либо внешние ключи для данных, связанных с пользователем.