Spec-Zone.ru › Django 4.2

Базы данных

В этом руководстве описывается поддержка 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",
    },
}

Если понятие базы данных по умолчанию не имеет смысла в контексте вашего проекта, вам нужно быть внимательными, чтобы всегда указывать используемую базу данных. Django требует определения записи базы данных по умолчанию, но словарь параметров может быть оставлен пустым, если он не будет использоваться. Для этого необходимо настроить 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__) мигрируемой модели. Его значение None для операций RunPython и RunSQL, если они не предоставляют его с помощью подсказок.

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, существующий объект в базе данных second будет перезаписан при сохранении p.

Вы можете избежать этого двумя способами. Во-первых, вы можете очистить первичный ключ экземпляра. Если у объекта нет первичного ключа, 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

Чтобы указать базу данных, из которой будет удалена модель, передайте ключевой аргумент using методу Model.delete(). Этот аргумент работает так же, как ключевой аргумент 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


# 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, Oracle или MySQL с InnoDB, это обеспечивается на уровне целостности базы данных — ограничения ключей на уровне базы данных предотвращают создание связей, которые невозможно проверить.

Однако, если вы используете SQLite или 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/4.2/topics/db/multi-db/

Spec-Zone.ru

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