Базы данных
В этом руководстве описана поддержка 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.db.utils.ConnectionDoesNotExist.
Синхронизация баз данных
Команда управления migrate работает с одной базой данных за раз. По умолчанию она работает с базой данных default , но с помощью опции --database вы можете указать, какую другую базу данных необходимо синхронизировать. Таким образом, чтобы синхронизировать все модели со всеми базами данных в первом примере выше, вам потребуется выполнить:
$ ./manage.py migrate $ ./manage.py migrate --database=users
Если вы не хотите, чтобы каждое приложение синхронизировалось с определенной базой данных, вы можете определить маршрутизатор баз данных маршрутизатор баз данных, который реализует политику, ограничивающую доступность определенных моделей.
Если, как и во втором примере выше, вы оставили базу данных default пустой, вы должны указать имя базы данных каждый раз, когда запускаете migrate. Пропуск имени базы данных вызовет ошибку. Для второго примера:
$ ./manage.py migrate --database=users $ ./manage.py migrate --database=customers
Использование других команд управления
Большинство других django-admin команд, взаимодействующих с базой данных, работают так же, как migrate — они работают только с одной базой данных за раз, используя --database для управления используемой базой данных.
Исключение из этого правила — команда makemigrations. Она проверяет историю миграций в базах данных, чтобы обнаружить проблемы с существующими файлами миграций (которые могут возникнуть при их редактировании), прежде чем создавать новые миграции. По умолчанию она проверяет только базу данных default, но обращается к методу allow_migrate() маршрутизаторов, если они установлены.
Добавлены проверки согласованности миграций. Проверки, основанные на маршрутизаторах баз данных, были добавлены в 1.10.1.
Автоматическое перенаправление на базу данных
Самый простой способ использования нескольких баз данных — это настройка схемы перенаправления на базу данных. Схема перенаправления по умолчанию обеспечивает, что объекты остаются «привязанными» к своей исходной базе данных (т. е. объект, извлеченный из базы данных 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, если маршрутизатор не имеет мнения. Это чисто операция проверки, используемая операциями внешнего ключа и многие ко многим для определения, разрешена ли связь между двумя объектами.
-
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 затем пытается каждый маршрутизатор по очереди, пока не найдется предложение базы данных. Если ни одно предложение не найдено, он пытается использовать текущий _state.db подсказки. Если экземпляр подсказки не был предоставлен или экземпляр в настоящее время не имеет состояния базы данных, главный маршрутизатор выделит default базу данных.
Пример
Только для примера!
Этот пример предназначен для демонстрации того, как инфраструктура маршрутизатора может быть использована для изменения использования базы данных. Он намеренно игнорирует некоторые сложные вопросы, чтобы продемонстрировать, как используются маршрутизаторы.
Этот пример не будет работать, если какие-либо модели в myapp содержат связи с моделями за пределами базы данных other. Связи между базами данных вводят проблемы целостности ссылок, с которыми Django в настоящее время не может справиться.
Описанная конфигурация мастер/реплика (называемая мастер/раб в некоторых базах данных) также имеет недостатки – она не предлагает никакого решения для обработки задержки репликации (т.е. несоответствия запросов, возникшие из-за времени, необходимого для распространения записи в реплики). Она также не учитывает взаимодействие транзакций со стратегией использования базы данных.
Итак, что это значит на практике? Давайте рассмотрим другую примерную конфигурацию. В ней будет несколько баз данных: одна для приложения auth, а все остальные приложения используют настройку мастер/реплика с двумя репликами для чтения. Вот параметры, определяющие эти базы данных:
DATABASES = {
'default': {},
'auth_db': {
'NAME': 'auth_db',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'swordfish',
},
'primary': {
'NAME': 'primary',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'spam',
},
'replica1': {
'NAME': 'replica1',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'eggs',
},
'replica2': {
'NAME': 'replica2',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'bacon',
},
}
Теперь нам нужно обработать маршрутизацию. Сначала мы хотим маршрутизатор, который знает, как отправлять запросы для приложения auth в auth_db:
class AuthRouter(object):
"""
A router to control all database operations on models in the
auth application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.app_label == 'auth':
return 'auth_db'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'auth':
return 'auth_db'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth app is involved.
"""
if obj1._meta.app_label == 'auth' or \
obj2._meta.app_label == 'auth':
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth app only appears in the 'auth_db'
database.
"""
if app_label == 'auth':
return db == 'auth_db'
return None
И мы также хотим маршрутизатор, который отправляет все остальные приложения в конфигурацию мастер/реплика и случайным образом выбирает реплику для чтения:
import random
class PrimaryReplicaRouter(object):
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen replica.
"""
return random.choice(['replica1', 'replica2'])
def db_for_write(self, model, **hints):
"""
Writes always go to primary.
"""
return 'primary'
def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the primary/replica pool.
"""
db_list = ('primary', 'replica1', 'replica2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
return True
Наконец, в файле настроек мы добавляем следующее (заменив path.to. на фактический путь к модулю(ам) Python, где определены маршрутизаторы):
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']
Порядок обработки маршрутизаторов имеет значение. Маршрутизаторы будут запрошены в том порядке, в котором они перечислены в настройке DATABASE_ROUTERS. В этом примере AuthRouter обрабатывается до PrimaryReplicaRouter, и в результате решения относительно моделей в auth обрабатываются до принятия любого другого решения. Если в настройке DATABASE_ROUTERS два маршрутизатора были бы перечислены в другом порядке, PrimaryReplicaRouter.allow_migrate() был бы обработан в первую очередь. Природа реализации PrimaryReplicaRouter как обработчика всех случаев означает, что все модели будут доступны во всех базах данных.
После установки этой настройки давайте запустим некоторый код Django:
>>> # This retrieval will be performed on the 'auth_db' database >>> fred = User.objects.get(username='fred') >>> fred.first_name = 'Frederick' >>> # This save will also be directed to 'auth_db' >>> fred.save() >>> # These retrieval will be randomly allocated to a replica database >>> dna = Person.objects.get(name='Douglas Adams') >>> # A new object has no database allocation when created >>> mh = Book(title='Mostly Harmless') >>> # This assignment will consult the router, and set mh onto >>> # the same database as the author object >>> mh.author = dna >>> # This save will force the 'mh' instance onto the primary database... >>> mh.save() >>> # ... but if we re-retrieve the object, it will come back on a replica >>> mh = Book.objects.get(title='Mostly Harmless')
В этом примере определен маршрутизатор для обработки взаимодействия с моделями из приложения auth, а другие маршрутизаторы для обработки взаимодействия со всеми другими приложениями. Если вы оставили свою базу данных default пустой и не хотите определять маршрутизатор базы данных для обработки всех приложений, не указанных иначе, ваши маршрутизаторы должны обрабатывать имена всех приложений в INSTALLED_APPS перед миграцией. См. Поведение приложений contrib для получения информации о приложениях contrib, которые должны быть вместе в одной базе данных.
Ручное выбор базы данных
Django также предоставляет API, который позволяет вам полностью контролировать использование базы данных в вашем коде. Ручная настройка базы данных будет иметь приоритет над базой данных, выделенной маршрутизатором.
Ручной выбор базы данных для запроса QuerySet
Вы можете выбрать базу данных для запроса QuerySet в любой точке цепочки QuerySet. Просто вызовите using() для QuerySet, чтобы получить другой 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()
Выбор базы данных для 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(MultiDBModelAdmin, self).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(MultiDBModelAdmin, self).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(MultiDBModelAdmin, self).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(MultiDBTabularInline, self).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(MultiDBTabularInline, self).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(MultiDBTabularInline, self).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 cursor = connections['my_db_alias'].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/1.11/topics/db/multi-db/