Базы данных
Данное руководство описывает поддержку 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__мигрируемой модели). Его значение равно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 пусто, базовый роутер выберет базу данных 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 , чтобы получить другой 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")
Выбрать базу данных для сохранения
Используйте ключевое слово 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, SQLite, Oracle или MySQL с InnoDB, это обеспечивается на уровне целостности базы данных — ограничения целостности на уровне базы данных предотвращают создание связей, которые невозможно проверить.
Однако, если вы используете MySQL с таблицами MyISAM, принудительной целостности ссылок нет; в результате вы, возможно, сможете «смоделировать» внешние ключи между базами данных. Тем не менее, такая настройка не поддерживается официально Django.
Поведение приложений contrib
Несколько приложений contrib содержат модели, и некоторые приложения зависят от других. Поскольку взаимосвязи между базами данных невозможны, это создаёт некоторые ограничения на то, как вы можете разделить эти модели по базам данных:
- каждый из
contenttypes.ContentType,authиadminможет храниться в любой базе данных при наличии подходящего маршрутизатора. -
модели
sessions.Session,Userиauthсвязаны между собой и связаны сGroup, поэтому они должны храниться в той же базе данных, что иContentType. -
sites.Siteзависит отPermission, поэтому его модели должны храниться в той же базе данных, что иContentType. -
authиredirectsзависят отflatpages, поэтому их модели должны храниться в той же базе данных, что иsites.
Кроме того, некоторые объекты автоматически создаются сразу после того, как migrate создаёт таблицу для их хранения в базе данных:
- по умолчанию
Site, ContentTypeдля каждой модели (включая те, которые не хранятся в этой базе данных),Permissionдля каждой модели (включая те, которые не хранятся в этой базе данных).
Для распространённых случаев использования нескольких баз данных нет необходимости иметь эти объекты в более чем одной базе данных. К распространённым случаям относятся первичная/резервная база данных и подключение к внешним базам данных. Поэтому рекомендуется написать маршрутизатор базы данных, который позволяет синхронизировать эти три модели только с одной базой данных. Используйте тот же подход для приложений contrib и сторонних приложений, которым не нужно хранить свои таблицы в нескольких базах данных.
Предупреждение
Если вы синхронизируете типы содержимого с более чем одной базой данных, имейте в виду, что их первичные ключи могут не совпадать между базами данных. Это может привести к повреждению данных или их потере.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.0/topics/db/multi-db/