Spec-Zone.ru › Django 2.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.db.utils.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)

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

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

Пример

Пример для демонстрационных целей!

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

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

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

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

DATABASES = {
    'default': {},
    'auth_db': {
        'NAME': 'auth_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'swordfish',
    },
    'primary': {
        'NAME': 'primary',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'spam',
    },
    'replica1': {
        'NAME': 'replica1',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'eggs',
    },
    'replica2': {
        'NAME': 'replica2',
        '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_list = ('primary', 'replica1', 'replica2')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            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, который позволяет вам сохранять полный контроль над использованием базы данных в вашем коде. Ручное указание базы данных будет иметь приоритет над базой данных, выделенной маршрутизатором.

Ручное выбор базы данных для запроса

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

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

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

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

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

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

Используйте ключевое слово 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/2.2/topics/db/multi-db/

Spec-Zone.ru

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