Spec-Zone.ru › Django 6.0

Несколько баз данных

В этом руководстве описана поддержка Django для работы с несколькими базами данных. В большей части остальной документации Django предполагается, что вы работаете с одной базой данных. Если вы хотите работать с несколькими базами данных, потребуется выполнить несколько дополнительных действий.

См. также

Сведения о тестировании с несколькими базами данных см. в разделе Поддержка нескольких баз данных.

Определение баз данных

Первый шаг к использованию Django более чем с одной базой данных — сообщить Django о серверах баз данных, которые вы будете использовать. Для этого служит параметр DATABASES. Этот параметр сопоставляет псевдонимы баз данных, с помощью которых можно ссылаться на определённую базу данных в Django, со словарём параметров для соответствующего подключения. Параметры во вложенных словарях подробно описаны в документации по DATABASES.

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

Ниже приведён пример фрагмента settings.py, определяющего две базы данных: базу данных PostgreSQL по умолчанию и базу данных MySQL с именем users:

DATABASES = {
    "default": {
        "NAME": "app_data",
        "ENGINE": "django.db.backends.postgresql",
        "USER": "postgres_user",
        "PASSWORD": "s3krit",
    },
    "users": {
        "NAME": "user_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "priv4te",
    },
}

Если концепция базы данных default не имеет смысла в контексте вашего проекта, необходимо всегда указывать базу данных, которую вы хотите использовать. Django требует, чтобы была определена запись базы данных default, но словарь параметров можно оставить пустым, если эта база данных не будет использоваться. Для этого необходимо настроить DATABASE_ROUTERS для моделей всех приложений, включая модели приложений из contrib и сторонних приложений, которые вы используете, чтобы никакие запросы не направлялись в базу данных по умолчанию. Ниже приведён пример фрагмента settings.py, определяющего две базы данных, не являющиеся базами по умолчанию; запись default намеренно оставлена пустой:

DATABASES = {
    "default": {},
    "users": {
        "NAME": "user_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "superS3cret",
    },
    "customers": {
        "NAME": "customer_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_cust",
        "PASSWORD": "veryPriv@ate",
    },
}

При попытке обратиться к базе данных, не определённой в параметре DATABASES, Django вызовет исключение django.utils.connection.ConnectionDoesNotExist.

Синхронизация баз данных

Команда управления migrate работает только с одной базой данных за раз. По умолчанию она работает с базой данных default, но с помощью параметра --database можно указать ей синхронизировать другую базу данных. Таким образом, чтобы синхронизировать все модели во всех базах данных из первого примера выше, необходимо выполнить:

$ ./manage.py migrate
$ ./manage.py migrate --database=users

Если вы не хотите синхронизировать каждое приложение с определённой базой данных, можно определить маршрутизатор баз данных, реализующий политику, которая ограничивает доступность определённых моделей.

Если, как во втором примере выше, вы оставили базу данных default пустой, необходимо указывать имя базы данных при каждом запуске migrate. Если не указать имя базы данных, возникнет ошибка. Для второго примера:

$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers

Использование других команд управления

Большинство других команд django-admin, работающих с базой данных, ведут себя так же, как migrate: они работают только с одной базой данных за раз, а используемая база данных задаётся с помощью --database.

Исключение из этого правила — команда makemigrations. Перед созданием новых миграций она проверяет историю миграций в базах данных, чтобы обнаружить проблемы с существующими файлами миграций (которые могут быть вызваны их редактированием). По умолчанию проверяется только база данных default, но команда учитывает метод allow_migrate() из маршрутизаторов, если они установлены.

Автоматическая маршрутизация баз данных

Самый простой способ использовать несколько баз данных — настроить схему маршрутизации баз данных. Схема маршрутизации по умолчанию гарантирует, что объекты остаются «привязанными» к исходной базе данных (то есть объект, полученный из базы данных foo, будет сохранён в той же базе данных). Схема маршрутизации по умолчанию гарантирует, что все запросы будут направляться в базу данных default, если база данных не указана.

Для включения схемы маршрутизации по умолчанию ничего делать не нужно: она предоставляется «из коробки» в каждом проекте Django. Однако если вы хотите реализовать более сложное поведение при распределении баз данных, можно определить и установить собственные маршрутизаторы баз данных.

Маршрутизаторы баз данных

Маршрутизатор баз данных — это класс, предоставляющий до четырёх методов:

db_for_read(model, **hints)

Предлагает базу данных, которую следует использовать для операций чтения объектов типа model.

Если операция с базой данных может предоставить дополнительную информацию, которая поможет выбрать базу данных, она будет передана в словаре hints. Сведения о допустимых подсказках приведены ниже.

Если предложение отсутствует, возвращает None.

db_for_write(model, **hints)

Предлагает базу данных, которую следует использовать для записи объектов типа Model.

Если операция с базой данных может предоставить дополнительную информацию, которая поможет выбрать базу данных, она будет передана в словаре hints. Сведения о допустимых подсказках приведены ниже.

Если предложение отсутствует, возвращает None.

allow_relation(obj1, obj2, **hints)

Возвращает True, если связь между obj1 и obj2 должна быть разрешена, False, если связь должна быть запрещена, или None, если у маршрутизатора нет мнения. Это исключительно операция проверки, используемая операциями с внешними ключами и связями «многие ко многим» для определения того, следует ли разрешить связь между двумя объектами.

Если ни один маршрутизатор не высказывает мнения (то есть все маршрутизаторы возвращают None), разрешены только связи внутри одной базы данных.

allow_migrate(db, app_label, model_name=None, **hints)

Определяет, разрешено ли выполнять операцию миграции в базе данных с псевдонимом db. Возвращает True, если операцию следует выполнить, False, если её выполнять не следует, или None, если у маршрутизатора нет мнения.

Позиционный аргумент app_label содержит метку мигрируемого приложения.

Большинство операций миграции задают для model_name значение model._meta.model_name (название модели __name__ в нижнем регистре), соответствующее мигрируемой модели. Для операций RunPython и RunSQL его значение равно None, если они не предоставляют его с помощью подсказок.

Некоторые операции используют hints для передачи маршрутизатору дополнительной информации.

Если задано model_name, hints обычно содержит класс модели под ключом 'model'. Обратите внимание: это может быть историческая модель, у которой может не быть пользовательских атрибутов, методов или менеджеров. Следует полагаться только на _meta.

Этот метод также можно использовать, чтобы определить доступность модели в заданной базе данных.

makemigrations всегда создаёт миграции для изменений моделей, однако если allow_migrate() возвращает False, все операции миграции для model_name будут молча пропущены при запуске migrate в базе данных db. Изменение поведения allow_migrate() для моделей, у которых уже есть миграции, может привести к повреждённым внешним ключам, лишним или отсутствующим таблицам. При проверке истории миграций команда makemigrations пропускает базы данных, в которых ни одному приложению не разрешено выполнять миграции.

Маршрутизатору необязательно предоставлять все эти методы — он может не реализовывать один или несколько из них. Если метод не реализован, Django пропустит этот маршрутизатор при выполнении соответствующей проверки.

Подсказки

Подсказки, полученные маршрутизатором базы данных, можно использовать для выбора базы данных, которой следует обработать запрос.

В настоящее время предоставляется только одна подсказка — instance, экземпляр объекта, связанный с выполняемой операцией чтения или записи. Это может быть сохраняемый экземпляр или экземпляр, добавляемый в связь «многие ко многим». В некоторых случаях подсказка с экземпляром не предоставляется. Маршрутизатор проверяет наличие подсказки с экземпляром и определяет, следует ли использовать её для изменения поведения маршрутизации.

Использование маршрутизаторов

Маршрутизаторы баз данных устанавливаются с помощью параметра DATABASE_ROUTERS. Этот параметр задаёт список имён классов, каждое из которых указывает маршрутизатор, который должен использоваться базовым маршрутизатором (django.db.router).

Базовый маршрутизатор используется операциями с базами данных Django для распределения обращений к базам данных. Когда запросу требуется определить, какую базу данных использовать, он обращается к базовому маршрутизатору, передавая модель и подсказку (если она доступна). Базовый маршрутизатор по очереди проверяет каждый класс маршрутизатора, пока один из них не предложит базу данных. Если ни один маршрутизатор не предложит базу данных, базовый маршрутизатор проверяет текущее значение instance._state.db экземпляра из подсказки. Если экземпляр из подсказки не предоставлен или instance._state.db равен None, базовый маршрутизатор выберет базу данных default.

Пример

Только для примера!

Этот пример демонстрирует, как инфраструктуру маршрутизаторов можно использовать для изменения порядка работы с базами данных. Чтобы показать, как используются маршрутизаторы, в нём намеренно не рассматриваются некоторые сложные вопросы.

Этот пример не будет работать, если какие-либо модели в myapp содержат связи с моделями за пределами базы данных other. Связи между базами данных создают проблемы с ссылочной целостностью, которые Django пока не может обрабатывать.

Описанная конфигурация «основная/реплики» (в некоторых базах данных её называют «ведущий/ведомые») также имеет недостатки: она не предусматривает решения проблемы задержки репликации (то есть несогласованности запросов, возникающей из-за времени, необходимого для передачи записи на реплики). Кроме того, в ней не учитывается взаимодействие транзакций со стратегией использования баз данных.

Итак, что это означает на практике? Рассмотрим другую примерную конфигурацию. В ней будет несколько баз данных: одна для приложения auth, а все остальные приложения будут использовать конфигурацию «основная/реплики» с двумя репликами для чтения. Вот параметры, задающие эти базы данных:

DATABASES = {
    "default": {},
    "auth_db": {
        "NAME": "auth_db_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "swordfish",
    },
    "primary": {
        "NAME": "primary_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "spam",
    },
    "replica1": {
        "NAME": "replica1_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "eggs",
    },
    "replica2": {
        "NAME": "replica2_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "bacon",
    },
}

Теперь нужно настроить маршрутизацию. Сначала нам нужен маршрутизатор, который будет направлять запросы для приложений auth и contenttypes в auth_db (модели auth связаны с ContentType, поэтому они должны храниться в одной базе данных):

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """

    route_app_labels = {"auth", "contenttypes"}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return "auth_db"
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return "auth_db"
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps 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 the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == "auth_db"
        return None

Кроме того, нам нужен маршрутизатор, направляющий все остальные приложения в конфигурацию «основная/реплики» и случайным образом выбирающий реплику для чтения:

import random


class PrimaryReplicaRouter:
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen replica.
        """
        return random.choice(["replica1", "replica2"])

    def db_for_write(self, model, **hints):
        """
        Writes always go to primary.
        """
        return "primary"

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_set = {"primary", "replica1", "replica2"}
        if obj1._state.db in db_set and obj2._state.db in db_set:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        All non-auth models end up in this pool.
        """
        return True

Наконец, в файл настроек добавим следующий фрагмент (заменив path.to. фактическим путём Python к модулю или модулям, в которых определены маршрутизаторы):

DATABASE_ROUTERS = ["path.to.AuthRouter", "path.to.PrimaryReplicaRouter"]

Порядок обработки маршрутизаторов имеет значение. Маршрутизаторы проверяются в том порядке, в котором они перечислены в параметре DATABASE_ROUTERS. В этом примере AuthRouter обрабатывается раньше PrimaryReplicaRouter, поэтому решения, относящиеся к моделям в auth, принимаются раньше всех остальных. Если бы в параметре DATABASE_ROUTERS два маршрутизатора были перечислены в обратном порядке, первым обрабатывался бы PrimaryReplicaRouter.allow_migrate(). Из-за того, что реализация PrimaryReplicaRouter обрабатывает все случаи, все модели были бы доступны во всех базах данных.

После установки этой конфигурации и миграции всех баз данных, как описано в разделе Синхронизация баз данных, выполним код Django:

>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username="fred")
>>> fred.first_name = "Frederick"

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

>>> # These retrieval will be randomly allocated to a replica database
>>> dna = Person.objects.get(name="Douglas Adams")

>>> # A new object has no database allocation when created
>>> mh = Book(title="Mostly Harmless")

>>> # This assignment will consult the router, and set mh onto
>>> # the same database as the author object
>>> mh.author = dna

>>> # This save will force the 'mh' instance onto the primary database...
>>> mh.save()

>>> # ... but if we re-retrieve the object, it will come back on a replica
>>> mh = Book.objects.get(title="Mostly Harmless")

В этом примере определён маршрутизатор для работы с моделями приложения auth, а другие маршрутизаторы отвечают за работу со всеми остальными приложениями. Если вы оставили базу данных default пустой и не хотите определять универсальный маршрутизатор баз данных для обработки всех приложений, не указанных отдельно, маршрутизаторы должны обрабатывать имена всех приложений в параметре INSTALLED_APPS до выполнения миграции. Сведения о приложениях contrib, которые должны находиться в одной базе данных, см. в разделе Поведение приложений contrib.

Выбор базы данных вручную

Django также предоставляет API, позволяющий полностью контролировать использование баз данных в коде. База данных, указанная вручную, имеет приоритет над базой данных, выбранной маршрутизатором.

Выбор базы данных вручную для QuerySet

Выбрать базу данных для QuerySet можно в любой момент в «цепочке» QuerySet. Вызовите using() для QuerySet, чтобы получить другой QuerySet, использующий указанную базу данных.

using() принимает один аргумент: псевдоним базы данных, в которой нужно выполнить запрос. Например:

>>> # This will run on the 'default' database.
>>> Author.objects.all()

>>> # So will this.
>>> Author.objects.using("default")

>>> # This will run on the 'other' database.
>>> Author.objects.using("other")

Выбор базы данных для save()

Используйте ключевое слово using для Model.save(), чтобы указать, в какую базу данных следует сохранить данные.

Например, чтобы сохранить объект в базе данных legacy_users, используйте следующее:

>>> my_object.save(using="legacy_users")

Если не указать using, метод save() сохранит данные в базе данных по умолчанию, выбранной маршрутизаторами.

Перемещение объекта из одной базы данных в другую

Если вы сохранили экземпляр в одной базе данных, может возникнуть соблазн использовать save(using=...) для его переноса в новую базу данных. Однако, если не принять соответствующих мер, это может привести к неожиданным последствиям.

Рассмотрим следующий пример:

>>> p = Person(name="Fred")
>>> p.save(using="first")  # (statement 1)
>>> p.save(using="second")  # (statement 2)

В инструкции 1 новый объект Person сохраняется в базе данных first. На этом этапе у p ещё нет первичного ключа, поэтому Django выполняет инструкцию SQL INSERT. Она создаёт первичный ключ, и Django присваивает его объекту p.

При сохранении в инструкции 2 у p уже есть значение первичного ключа, и Django попытается использовать этот первичный ключ в новой базе данных. Если это значение первичного ключа ещё не используется в базе данных second, проблем не возникнет — объект будет скопирован в новую базу данных.

Однако если первичный ключ p уже используется в базе данных second, при сохранении p существующий объект в базе данных second будет перезаписан.

Этого можно избежать двумя способами. Во-первых, можно очистить первичный ключ экземпляра. Если у объекта нет первичного ключа, Django будет считать его новым и предотвратит потерю данных в базе данных second:

>>> p = Person(name="Fred")
>>> p.save(using="first")
>>> p.pk = None  # Clear the primary key.
>>> p.save(using="second")  # Write a completely new object.

Второй вариант — использовать параметр force_insert для save(), чтобы гарантировать выполнение Django инструкции SQL INSERT:

>>> p = Person(name="Fred")
>>> p.save(using="first")
>>> p.save(using="second", force_insert=True)

Это гарантирует, что человек с именем Fred будет иметь одинаковый первичный ключ в обеих базах данных. Если при попытке сохранить его в базе данных second этот первичный ключ уже используется, возникнет ошибка.

Выбор базы данных для удаления

По умолчанию вызов удаления существующего объекта будет выполнен в той же базе данных, из которой объект был получен:

>>> u = User.objects.using("legacy_users").get(username="fred")
>>> u.delete()  # will delete from the `legacy_users` database

Чтобы указать базу данных, из которой нужно удалить модель, передайте в метод Model.delete() именованный аргумент using. Этот аргумент работает так же, как именованный аргумент using для save().

Например, при переносе пользователя из базы данных legacy_users в базу данных new_users можно использовать следующие команды:

>>> user_obj.save(using="new_users")
>>> user_obj.delete(using="legacy_users")

Использование менеджеров с несколькими базами данных

Используйте метод db_manager() менеджеров, чтобы предоставить им доступ к базе данных, отличной от базы данных по умолчанию.

Предположим, у вас есть пользовательский метод менеджера, который обращается к базе данных, — User.objects.create_user(). Поскольку create_user() — это метод менеджера, а не метод QuerySet, вызвать User.objects.using('new_users').create_user() нельзя. (Метод create_user() доступен только у User.objects — менеджера, но не у объектов QuerySet, полученных из менеджера.) Решение — использовать db_manager(), например так:

User.objects.db_manager("new_users").create_user(...)

db_manager() возвращает копию менеджера, привязанную к указанной базе данных.

Использование get_queryset() с несколькими базами данных

Если вы переопределяете get_queryset() в менеджере, обязательно вызовите метод родительского класса (с помощью super()) или надлежащим образом обработайте атрибут _db менеджера (строку с именем используемой базы данных).

Например, если вы хотите возвращать пользовательский класс QuerySet из метода get_queryset, можно сделать следующее:

class MyManager(models.Manager):
    def get_queryset(self):
        qs = CustomQuerySet(self.model)
        if self._db is not None:
            qs = qs.using(self._db)
        return qs

Использование нескольких баз данных в интерфейсе администратора Django

Интерфейс администратора Django не поддерживает работу с несколькими базами данных напрямую. Если вы хотите предоставить интерфейс администратора для модели в базе данных, отличной от указанной в цепочке маршрутизаторов, необходимо написать пользовательские классы ModelAdmin, которые укажут администратору использовать для содержимого определённую базу данных.

Объекты ModelAdmin содержат следующие методы, которые необходимо настроить для поддержки нескольких баз данных:

class MultiDBModelAdmin(admin.ModelAdmin):
    # A handy constant for the name of the alternate database.
    using = "other"

    def save_model(self, request, obj, form, change):
        # Tell Django to save objects to the 'other' database.
        obj.save(using=self.using)

    def delete_model(self, request, obj):
        # Tell Django to delete objects from the 'other' database
        obj.delete(using=self.using)

    def get_queryset(self, request):
        # Tell Django to look for objects on the 'other' database.
        return super().get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super().formfield_for_foreignkey(
            db_field, request, using=self.using, **kwargs
        )

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super().formfield_for_manytomany(
            db_field, request, using=self.using, **kwargs
        )

Представленная здесь реализация поддерживает стратегию работы с несколькими базами данных, при которой все объекты заданного типа хранятся в определённой базе данных (например, все объекты User находятся в базе данных other). Если ваш сценарий использования нескольких баз данных сложнее, ваш ModelAdmin должен соответствовать этой стратегии.

Объекты InlineModelAdmin можно обрабатывать аналогичным образом. Для них требуется настроить три метода:

class MultiDBTabularInline(admin.TabularInline):
    using = "other"

    def get_queryset(self, request):
        # Tell Django to look for inline objects on the 'other' database.
        return super().get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super().formfield_for_foreignkey(
            db_field, request, using=self.using, **kwargs
        )

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super().formfield_for_manytomany(
            db_field, request, using=self.using, **kwargs
        )

Определив классы администрирования моделей, их можно зарегистрировать в любом экземпляре Admin:

from django.contrib import admin
from myapp.models import Author, Book, Publisher

# Import our custom ModelAdmin and TabularInline from where they're defined.
from myproject.admin import MultiDBModelAdmin, MultiDBTabularInline


# Specialize the multi-db admin objects for use with specific models.
class BookInline(MultiDBTabularInline):
    model = Book


class PublisherAdmin(MultiDBModelAdmin):
    inlines = [BookInline]


admin.site.register(Author, MultiDBModelAdmin)
admin.site.register(Publisher, PublisherAdmin)

othersite = admin.AdminSite("othersite")
othersite.register(Publisher, MultiDBModelAdmin)

В этом примере настроены два сайта администратора. На первом сайте отображаются объекты Author и Publisher; для объектов Publisher предусмотрен табличный встроенный интерфейс со списком книг, опубликованных этим издателем. На втором сайте отображаются только издатели, без встроенных интерфейсов.

Использование необработанных курсоров с несколькими базами данных

При использовании нескольких баз данных можно получить подключение (и курсор) к определённой базе данных с помощью django.db.connections. django.db.connections — это объект, похожий на словарь, который позволяет получить конкретное подключение по его псевдониму:

from django.db import connections

with connections["my_db_alias"].cursor() as cursor:
    ...

Ограничения при использовании нескольких баз данных

Связи между базами данных

В настоящее время Django не поддерживает связи внешних ключей и «многие ко многим», охватывающие несколько баз данных. Если вы использовали маршрутизатор для распределения моделей по разным базам данных, все определённые для этих моделей связи внешних ключей и «многие ко многим» должны находиться в одной базе данных.

Это связано с обеспечением ссылочной целостности. Чтобы поддерживать связь между двумя объектами, Django должен знать, что первичный ключ связанного объекта действителен. Если первичный ключ хранится в отдельной базе данных, проверить его допустимость не так просто.

Если вы используете Postgres, SQLite, Oracle или MySQL с InnoDB, это обеспечивается на уровне целостности базы данных: ограничения ключей на уровне базы данных предотвращают создание связей, которые невозможно проверить.

Однако при использовании MySQL с таблицами MyISAM ссылочная целостность не обеспечивается; поэтому можно попытаться создать «фиктивные» внешние ключи между базами данных. Тем не менее Django официально не поддерживает такую конфигурацию.

Поведение приложений contrib

Некоторые приложения contrib содержат модели, а некоторые приложения зависят от других. Поскольку связи между базами данных невозможны, это накладывает ограничения на распределение таких моделей по базам данных:

  • каждую из моделей contenttypes.ContentType, sessions.Session и sites.Site можно хранить в любой базе данных при наличии подходящего маршрутизатора.
  • Модели auth — User, Group и Permission — связаны друг с другом и с ContentType, поэтому их необходимо хранить в одной базе данных с ContentType.
  • Приложение admin зависит от auth, поэтому его модели должны находиться в одной базе данных с auth.
  • Приложения flatpages и redirects зависят от sites, поэтому их модели должны находиться в одной базе данных с sites.

Кроме того, некоторые объекты создаются автоматически сразу после того, как migrate создаёт в базе данных таблицу для их хранения:

  • объект Site по умолчанию;
  • объект ContentType для каждой модели (включая модели, которые не хранятся в этой базе данных);
  • объекты Permission для каждой модели (включая модели, которые не хранятся в этой базе данных).

В типичных конфигурациях с несколькими базами данных нет смысла хранить эти объекты более чем в одной базе данных. К таким конфигурациям относятся схемы «основная/реплики» и подключение к внешним базам данных. Поэтому рекомендуется написать маршрутизатор баз данных, который разрешает синхронизировать эти три модели только с одной базой данных. Аналогичным образом поступайте с приложениями contrib и сторонними приложениями, которым не требуется хранить таблицы в нескольких базах данных.

Предупреждение

Если вы синхронизируете типы содержимого более чем с одной базой данных, имейте в виду, что их первичные ключи могут различаться в разных базах данных. Это может привести к повреждению или потере данных.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/6.0/topics/db/multi-db/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API