Завдяки коментарям до мого запитання я провів деякі дослідження і прийшов до наступних висновків.
Використання декількох баз даних призводить до створення таблиці django_migrations
при використанні міграцій. Немає можливості записувати міграції лише в одній таблиці django_migrations
, як коментар пояснює Каміля Ніскі . Це зрозуміло після прочитання файлу django/db/migrations/recorder.py
.
Я проілюструю приклад із проектом foo
та додаткомbar
всередині проекту. У додатку bar
є лише одна модель Baz
.
Ми створюємо проект:
django-admin startproject foo
Тепер у нас є цей вміст у головному каталозі проектів:
- foo
- manage.py
У мене є звичка групувати всі програми в каталозі проектів:
mkdir foo/bar
python manage.py bar foo/bar
У файлі foo/settings.py
ми налаштовуємо налаштування для використання двох різних баз даних для цілей цього прикладуsqlite3
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db1.sqlite3'),
},
'remote': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),
}
}
Тепер ми виконуємо міграції:
python manage.py migrate --database=default
При цьому виконуються всі міграції, частина --database=default
є необов'язковою, оскільки якщо Django не вказано, використовується база даних за замовчуванням.
Операції для виконання:
Застосовуйте всі міграції: адміністратор, auth, типи вмісту, сеанси
Запуск міграцій:
Застосування типів вмісту.0001_initial ... ОК
Застосування auth.0001_initial ... ОК
Застосування admin.0001_initial ... ОК
Застосування admin.0002_logentry_remove_auto_add ... ОК
Застосування admin.0003_logentry_addgery_flag_choices ... ОК
Застосування типів вмісту.0002_remove_content_type_name ... ОК
Застосування auth.0002_alter_permission_name_max_length ... ОК
Застосування auth.0003_alter_user_email_max_length ... ОК
Застосування auth.0004_alter_user_username_opts ... ОК
Застосування auth.0005_alter_user_last_login_null ... ОК
Застосування auth.0006_require_contenttypes_0002 ... ОК
Застосування auth.0007_alter_validators_add_error_messages ... ОК
Застосування auth.0008_alter_user_username_max_length ... ОК
Застосування auth.0009_alter_user_last_name_max_length ... ОК
Застосування auth.0010_alter_group_name_max_length ... ОК
Застосування auth.0011_update_proxy_permissions ... ОК
Застосування сеансів.0001_initial ... ОК
Django застосував усі міграції до бази даних за замовчуванням:
1 типи вмісту 0001_initial 2019-11-13 16: 51: 04.767382
2 авт 0001_initial 2019-11-13 16: 51: 04.792245
3 адміністратор 0001_initial 2019-11-13 16: 51: 04.827454
4 адмін 0002_logentr 2019-11-13 16: 51: 04.846627
5 адміністратор 0003_logentr 2019-11-13 16: 51: 04.864458
6 типів вмісту 0002_remove_ 2019-11-13 16: 51: 04.892220
7 авт 0002_alter_p 2019-11-13 16: 51: 04.906449
8 авт 0003_alter_u 2019-11-13 16: 51: 04.923902
9 авт 0004_alter_u 2019-11-13 16: 51: 04.941707
10 авт 0005_alter_u 2019-11-13 16: 51: 04.958371
11 авт 0006_потрібно 2019-11-13 16: 51: 04.965527
12 авт 0007_alter_v 2019-11-13 16: 51: 04.981532
13 авт 0008_alter_u 2019-11-13 16: 51: 05.004149
14 авт 0009_alter_u 2019-11-13 16: 51: 05.019705
15 авт 0010_alter_g 2019-11-13 16: 51: 05.037023
16 авт. 0011_update_ 2019-11-13 16: 51: 05.054449
17 сеансів 0001_initial 2019-11-13 16: 51: 05.063868
Тепер ми створюємо модель Baz
:
models.py
:
from django.db import models
class Baz(models.Model):
name = models.CharField(max_length=255, unique=True)
зареєструйте додаток bar
у INSTALLED_APPS
( foo/settings.py
) та створіть їхграші:
python manage.py makemigrations bar
Перш ніж запустити міграції, які ми створюємо routers.py
всередині bar
додатка:
клас BarRouter (об’єкт):
def db_for_read (самостійна модель, ** підказки):
if model._meta.app_label == 'бар':
повернути "віддалений"
повернути Ні
def db_for_write (самостійна модель, ** підказки):
if model._meta.app_label == 'бар':
повернути "віддалений"
повернути Ні
def enable_relation (self, obj1, obj2, ** підказки):
повернути Ні
def enable_migrate (self, db, app_label, model_name = Немає, ** підказки):
якщо app_label == 'бар':
return db == 'віддалений'
якщо db == 'віддалений':
повернути Неправдиво
повернути Ні
і зареєструйте його у foo/settings.py
:
DATABASE_ROUTERS = ['foo.bar.routers.BarRouter']
Тепер наївним підходом було б запуск міграцій bar
в remote
базу даних:
python manage.py migrate bar --database=remote
Операції для виконання:
Застосувати всі міграції: bar
Запуск міграцій:
Застосування bar.0001_initial ... ОК
Міграції застосовано до remote
бази даних:
1 бар 0001_initial 2019-11-13 17: 32: 39.701784
Коли ми запускаємо:
python manage.py runserver
буде подано таке попередження:
У вас є 1 неприкладена міграція. Ваш проект може не працювати належним чином, поки ви не застосуєте міграцію для додатка: бар.
Запустіть "python Manag.py migrate", щоб застосувати їх.
Здається, все працює добре. Однак це попередження не задовольняє.
Правильним способом було б запустити всі міграції для кожної бази даних, як пропонується у цій відповіді .
Це виглядатиме так:
python manage.py migrate --database=default
python manage.py migrate --database=remote
і після створення міграцій для bar
:
python manage.py migrate bar --database=default
python manage.py migrate bar --database=remote
Маршрутизатор подбає про те, щоб таблиця bar_baz
була створена лише в remote
базі даних, але Django позначить міграції як застосовані в обох базах даних. Також столи для auth
, admin
, sessions
і т.д. , будуть створені тільки в default
базі даних, як зазначено в routers.py
. Таблиця django_migrations
в remote
базі даних матиме записи і про ці міграції.
Це тривале читання, але я сподіваюсь, що він прояснить це питання, на мою думку, не до кінця поясненого питання в офіційній документації .