Настройка нескольких баз данных в Django
Введение
Я прочитал Документацию по Django: Multiple databases, но, похоже, это не работает для меня после обновления с 3.2 до 4.0. Были сделаны другие изменения, но поскольку я работаю в среде разработки, я решил удалить все предыдущие миграции и запустить ./manage.py makemigrations снова, но это не помогло решить проблему.
Определение маршрутизатора
Сначала вот как я определяю маршрутизатор. Вы заметите, что он почти идентичен примеру, но я включаю почти все в базу данных admin_db (с двумя исключениями: пользовательские приложения api.dictionary и api.pdf).
/api/authentication/routers.py
class AdminDBRouter:
"""
A router to control all database operations on models in the authentication application, all and any dependent applications, and Django administrative applications.
"""
route_app_labels = {
'admin',
'auth',
'authentication',
'contenttypes',
'sessions',
'sites',
'token_blacklist',
}
def db_for_read(self, model, **hints):
"""
Attempts to read models defined in any app in 'self.route_app_labels' go to 'admin_db'.
"""
if model._meta.app_label in self.route_app_labels:
return 'admin_db'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write models defined in any app in 'self.route_app_labels' go to 'admin_db'.
"""
if model._meta.app_label in self.route_app_labels:
return 'admin_db'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in any app defined in 'self.route_app_labels' is involved.
"""
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):
"""
Make sure any app in 'self.route_app_labels' only appears in the 'admin_db' database.
"""
if app_label in self.route_app_labels:
return db == 'admin_db'
return None
Настройки
А вот как я устанавливаю приложения/базы данных в настройках:
/project_name/settings.py
INSTALLED_APPS = [
'api',
'api.authentication',
'api.dictionary',
'api.pdf',
'corsheaders',
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'django_smtp_ssl',
'rest_framework',
'rest_framework_simplejwt',
'rest_framework_simplejwt.token_blacklist',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': DEFAULT_DATABASE_NAME,
'USER': DEFAULT_DATABASE_USER,
'PASSWORD': DEFAULT_DATABASE_PASSWORD,
'TEST': {
'DEPENDENCIES': ['admin_db'],
},
},
'admin_db': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': ADMIN_DATABASE_NAME,
'USER': ADMIN_DATABASE_USER,
'PASSWORD': ADMIN_DATABASE_PASSWORD,
'TEST': {
'DEPENDENCIES': [],
},
},
}
DATABASE_ROUTERS = ['api.authentication.routers.AdminDBRouter']
Создание миграций
Как было сказано ранее, я выполнил команду makemigrations. Вот вывод команды:
(.venv) arch-laptop back-end > ./manage.py makemigrations
Migrations for 'dictionary':
api/dictionary/migrations/0001_initial.py
- Create model Category
- Create model MP3
- Create model Word
- Create model ThesaurusEntry
- Create model Icon
- Create model DictionaryEntry
Migrations for 'pdf':
api/pdf/migrations/0001_initial.py
- Create model Category
- Create model PDF
Migrations for 'authentication':
api/authentication/migrations/0001_initial.py
- Create model User
...и вот файлы, которые он сгенерировал:
/api/authentication/migrations/0001_initial.py
# Generated by Django 4.0.3 on 2022-03-01 21:18
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='User',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='datetime created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='datetime updated')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(default=None, max_length=64, unique=True, verbose_name='username')),
('email', models.EmailField(default=None, max_length=254, unique=True, verbose_name='email address')),
('is_active', models.BooleanField(default=True, verbose_name='is active')),
('is_staff', models.BooleanField(default=False, verbose_name='is staff')),
('is_verified', models.BooleanField(default=False, verbose_name='is verified')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
],
options={
'abstract': False,
},
),
]
/api/dictionary/migrations/0001_initial.py
/api/pdf/migrations/0001_initial.py
# Generated by Django 4.0.3 on 2022-03-01 21:18
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='datetime created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='datetime updated')),
('name', models.CharField(max_length=40, unique=True, verbose_name='Name')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PDF',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='datetime created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='datetime updated')),
('title', models.CharField(max_length=80, verbose_name='Title')),
('pdf', models.FileField(max_length=160, upload_to='pdf', verbose_name='PDF')),
('_hash', models.BinaryField(max_length=16, null=True, verbose_name='MD5 hash')),
('categories', models.ManyToManyField(to='pdf.category')),
],
options={
'abstract': False,
},
),
]
Запуск миграций
Здесь я сталкиваюсь с проблемой.
Summary
Как видите, обе базы данных получают все изменения, примененные к ним. Я пробовал устанавливать точки останова и операторы печати в методах маршрутизатора, но правильные значения возвращались. Странно то, что у меня все работало, когда были только приложения authentication и dictionary, но как только я ввел приложение pdf, у меня начались проблемы. Что я могу попробовать?