Настройка нескольких баз данных в 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, у меня начались проблемы. Что я могу попробовать?

Вернуться на верх