Базы данных
Это руководство описывает поддержку 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) -
Предложить базу данных, которая должна использоваться для записей объектов типа Модель.
Если операция базы данных способна предоставить дополнительную информацию, которая может помочь в выборе базы данных, она будет предоставлена в словаре
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 затем пытается каждый маршрутизатор по очереди, пока не найдет рекомендацию базы данных. Если рекомендация не найдена, он пытается использовать текущее состояние подсказки. Если подсказка не была предоставлена или состояние подсказки 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, позволяющий сохранять полный контроль над использованием базы данных в вашем коде. Ручное указание базы данных для распределения имеет приоритет над базой данных, выделенной маршрутизатором.
Ручное выбор базы данных для запроса
Вы можете выбрать базу данных для запроса в любой момент в цепочке. Вызовите 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/3.2/topics/db/multi-db/