Базы данных
Это руководство описывает поддержку 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) -
Предложить базу данных, которая должна использоваться для записи объектов типа Модель.
Если операция базы данных может предоставить дополнительную информацию, которая может помочь в выборе базы данных, она будет предоставлена в словаре
hints. Сведения о допустимых подсказках приведены ниже.Возвращает
None, если нет предложения.
-
allow_relation(obj1, obj2, **hints) -
Возвращает
True, если отношение междуobj1иobj2должно быть разрешено,False, если отношение должно быть предотвращено, илиNone, если у маршрутизатора нет мнения. Это чисто операция проверки, используемая операциями внешнего ключа и многие ко многим для определения, должно ли быть разрешено отношение между двумя объектами.Если ни один маршрутизатор не имеет мнения (то есть все маршрутизаторы возвращают
None), разрешены только отношения внутри одной базы данных.
-
allow_migrate(db, app_label, model_name=None, **hints) -
Определить, разрешено ли выполнять операцию миграции в базе данных с псевдонимом
db. ВозвращаетTrue, если операция должна выполняться,False, если она не должна выполняться, илиNone, если у маршрутизатора нет мнения.Позиционный аргумент
app_label— это метка приложения, которое мигрируется.model_nameустанавливается большинством операций миграции в значениеmodel._meta.model_name(нижнего регистра модели__name__) мигрируемой модели. Его значение равноNoneдля операцийRunPythonиRunSQL, если они не предоставят его с помощью подсказок.hintsиспользуются некоторыми операциями для передачи дополнительной информации маршрутизатору.Когда
model_nameустановлено,hintsобычно содержит класс модели по ключу'model'. Обратите внимание, что это может быть историческая модель, и поэтому не будет иметь никаких пользовательских атрибутов, методов или менеджеров. Вы должны полагаться только на_meta.Этот метод также может использоваться для определения доступности модели в данной базе данных.
makemigrationsвсегда создаёт миграции для изменений модели, но еслиallow_migrate()возвращаетFalse, любые операции миграции дляmodel_nameбудут проигнорированы при запускеmigrateв базе данныхdb. Изменение поведенияallow_migrate()для моделей, у которых уже есть миграции, может привести к нарушению внешних ключей, дополнительных таблиц или отсутствующих таблиц. Когдаmakemigrationsпроверяет историю миграций, он пропускает базы данных, где ни одно приложение не может мигрировать.
Маршрутизатор не обязан предоставлять все эти методы — он может опустить один или несколько из них. Если один из методов пропущен, Django пропустит этот маршрутизатор при выполнении соответствующей проверки.
Подсказки
Подсказки, полученные маршрутизатором базы данных, могут использоваться для определения базы данных, которая должна получить данный запрос.
В настоящее время единственной подсказкой, которая будет предоставлена, является instance, экземпляр объекта, который связан с операцией чтения или записи, которая выполняется. Это может быть экземпляр, который сохраняется, или экземпляр, который добавляется в отношении многие ко многим. В некоторых случаях подсказка экземпляра вообще не будет предоставлена. Маршрутизатор проверяет наличие подсказки экземпляра и определяет, следует ли использовать эту подсказку для изменения поведения маршрутизации.
Использование маршрутизаторов
Маршрутизаторы баз данных устанавливаются с помощью параметра DATABASE_ROUTERS. Этот параметр определяет список имён классов, каждый из которых задаёт маршрутизатор, который должен использоваться базовым маршрутизатором (django.db.router).
Базовый маршрутизатор используется операциями базы данных Django для распределения использования баз данных. Всякий раз, когда запрос нуждается в том, чтобы узнать, какую базу данных использовать, он вызывает базовый маршрутизатор, предоставляя модель и подсказку (если она доступна). Базовый маршрутизатор пытается использовать каждый класс маршрутизатора по очереди, пока один не вернёт предложение по базе данных. Если ни один маршрутизатор не возвращает предложения, базовый маршрутизатор пытается использовать текущее instance._state.db подсказки экземпляра. Если подсказка экземпляра не была предоставлена или instance._state.db имеет значение None, базовый маршрутизатор распределит базу данных default.
Пример
Только для примера!
Этот пример предназначен для демонстрации того, как можно использовать инфраструктуру маршрутизатора для изменения использования баз данных. Он намеренно игнорирует некоторые сложные вопросы, чтобы продемонстрировать, как используются маршрутизаторы.
Этот пример не будет работать, если какая-либо из моделей в myapp содержит связи с моделями за пределами базы данных other. Связи между базами данных создают проблемы целостности ссылок, с которыми Django в настоящее время не может справиться.
Описанная конфигурация мастер/раб (называемая у некоторых баз данных мастер/ведомый) также является неполной — она не предлагает никакого решения для обработки задержки репликации (то есть несоответствия запросов, вызванные временем, необходимым для распространения записи на реплики). Также не учитывается взаимодействие транзакций со стратегией использования базы данных.
Итак, что это значит на практике? Давайте рассмотрим другую примерную конфигурацию. В ней будет несколько баз данных: одна для приложения auth и все остальные приложения, использующие настройку мастер/раб с двумя читаемыми репликами. Вот настройки, определяющие эти базы данных:
DATABASES = {
"default": {},
"auth_db": {
"NAME": "auth_db_name",
"ENGINE": "django.db.backends.mysql",
"USER": "mysql_user",
"PASSWORD": "swordfish",
},
"primary": {
"NAME": "primary_name",
"ENGINE": "django.db.backends.mysql",
"USER": "mysql_user",
"PASSWORD": "spam",
},
"replica1": {
"NAME": "replica1_name",
"ENGINE": "django.db.backends.mysql",
"USER": "mysql_user",
"PASSWORD": "eggs",
},
"replica2": {
"NAME": "replica2_name",
"ENGINE": "django.db.backends.mysql",
"USER": "mysql_user",
"PASSWORD": "bacon",
},
}
Теперь нам нужно обработать маршрутизацию. Сначала нам нужен маршрутизатор, который знает, что нужно отправлять запросы для приложений auth и contenttypes в auth_db (модели auth связаны с ContentType, поэтому они должны храниться в одной базе данных):
class AuthRouter:
"""
A router to control all database operations on models in the
auth and contenttypes applications.
"""
route_app_labels = {"auth", "contenttypes"}
def db_for_read(self, model, **hints):
"""
Attempts to read auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return "auth_db"
return None
def db_for_write(self, model, **hints):
"""
Attempts to write auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return "auth_db"
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth or contenttypes apps is
involved.
"""
if (
obj1._meta.app_label in self.route_app_labels
or obj2._meta.app_label in self.route_app_labels
):
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth and contenttypes apps only appear in the
'auth_db' database.
"""
if app_label in self.route_app_labels:
return db == "auth_db"
return None
И нам также нужен маршрутизатор, который отправляет все остальные приложения в конфигурацию мастер/раб и случайным образом выбирает реплику для чтения:
import random
class PrimaryReplicaRouter:
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen replica.
"""
return random.choice(["replica1", "replica2"])
def db_for_write(self, model, **hints):
"""
Writes always go to primary.
"""
return "primary"
def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the primary/replica pool.
"""
db_set = {"primary", "replica1", "replica2"}
if obj1._state.db in db_set and obj2._state.db in db_set:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
return True
Наконец, в файле настроек мы добавим следующее (заменив path.to. фактическим путём к модулю/модулям, где определены маршрутизаторы):
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
from myapp.models import Author, Book, Publisher
# Import our custom ModelAdmin and TabularInline from where they're defined.
from myproject.admin import MultiDBModelAdmin, MultiDBTabularInline
# 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.2/topics/db/multi-db/