PRO

Как настроить Django для работы с несколькими базами данных?

Для работы с несколькими базами в Django описывают несколько подключений в DATABASES, используют .using() для явного выбора базы и при необходимости создают database router. Router определяет, в какую базу отправлять операции чтения, записи, миграции и связи моделей.
Подробный ответ

Настройка подключений

В settings.py можно определить несколько баз данных. База с ключом default обязательна, остальные получают собственные alias.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'main_db',
        'HOST': 'db-primary',
    },
    'analytics': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'analytics_db',
        'HOST': 'db-analytics',
    },
}

Явный выбор базы

Для разовых операций базу можно выбрать явно через using().

events = Event.objects.using('analytics').filter(event_type='login')
Event.objects.using('analytics').create(event_type='purchase')

Database router

Если правила маршрутизации должны применяться автоматически, создают router с методами db_for_read, db_for_write, allow_relation и allow_migrate. Затем путь к router добавляют в DATABASE_ROUTERS.

class AnalyticsRouter:
    route_app_labels = {'analytics'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'analytics'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'analytics'
        return None

    def allow_migrate(self, db, app_label, **hints):
        if app_label in self.route_app_labels:
            return db == 'analytics'
        return db == 'default'

Миграции

Миграции запускают отдельно для каждой базы, если это предусмотрено архитектурой.

python manage.py migrate --database=default
python manage.py migrate --database=analytics

Ограничения

Django не поддерживает SQL JOIN между разными базами данных. Транзакции тоже работают в пределах одного соединения, поэтому распределённые операции требуют отдельного проектирования, например eventual consistency, outbox pattern или компенсационных действий.

Как ответить на собеседовании

Я добавляю несколько подключений в DATABASES и либо выбираю базу через using(), либо настраиваю database router. При этом учитываю, что нельзя делать JOIN и обычные атомарные транзакции между разными базами, поэтому границы данных должны быть спроектированы заранее.

Оцени свой прогресс

Честно оцени своё понимание этого вопроса, чтобы мы могли построить твой учебный трек максимально эффективно.
Читать в блоге