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