感谢对我的问题的评论,我做了一些研究并得出了以下发现。
使用多个数据库会导致创建一个表django_migrations
当使用迁移时。没有选项可以仅在一张表中记录迁移django_migrations
,正如来自的评论卡米尔·尼斯基 https://stackoverflow.com/users/9820085/kamil-niski解释说。读完文件就清楚了django/db/migrations/recorder.py https://github.com/django/django/blob/master/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 将使用默认数据库。
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
Django 已将所有迁移应用到默认数据库:
1 contenttypes 0001_initial 2019-11-13 16:51:04.767382
2 auth 0001_initial 2019-11-13 16:51:04.792245
3 admin 0001_initial 2019-11-13 16:51:04.827454
4 admin 0002_logentr 2019-11-13 16:51:04.846627
5 admin 0003_logentr 2019-11-13 16:51:04.864458
6 contenttypes 0002_remove_ 2019-11-13 16:51:04.892220
7 auth 0002_alter_p 2019-11-13 16:51:04.906449
8 auth 0003_alter_u 2019-11-13 16:51:04.923902
9 auth 0004_alter_u 2019-11-13 16:51:04.941707
10 auth 0005_alter_u 2019-11-13 16:51:04.958371
11 auth 0006_require 2019-11-13 16:51:04.965527
12 auth 0007_alter_v 2019-11-13 16:51:04.981532
13 auth 0008_alter_u 2019-11-13 16:51:05.004149
14 auth 0009_alter_u 2019-11-13 16:51:05.019705
15 auth 0010_alter_g 2019-11-13 16:51:05.037023
16 auth 0011_update_ 2019-11-13 16:51:05.054449
17 sessions 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
into INSTALLED_APPS
(foo/settings.py
)并创建迁移:
python manage.py makemigrations bar
在运行我们创建的迁移之前routers.py
在 - 的里面bar
app:
class BarRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'bar':
return 'remote'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'bar':
return 'remote'
return None
def allow_relation(self, obj1, obj2, **hints):
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'bar':
return db == 'remote'
if db == 'remote':
return False
return None
并将其注册到foo/settings.py
:
DATABASE_ROUTERS = ['foo.bar.routers.BarRouter']
现在天真的方法是运行迁移bar
进入remote
数据库:
python manage.py migrate bar --database=remote
Operations to perform:
Apply all migrations: bar
Running migrations:
Applying bar.0001_initial... OK
迁移已应用于remote
数据库:
1 bar 0001_initial 2019-11-13 17:32:39.701784
当我们运行时:
python manage.py runserver
将发出以下警告:
您有 1 项未应用的迁移。您的项目可能无法正常运行
直到您应用应用程序的迁移:栏。
运行“python manage.py migrate”来应用它们。
不过一切似乎都运行良好。然而,这个警告并不能令人满意。
正确的方法是按照本中的建议为每个数据库运行所有迁移answer https://stackoverflow.com/a/35614973/3848833.
它看起来像这样:
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
in the remote
数据库也会有这些迁移的记录。
这是一篇很长的阅读,但我希望它能对这个问题有所启发,在我看来,官方没有彻底解释这个问题文档 https://docs.djangoproject.com/en/2.2/topics/db/multi-db/#synchronizing-your-databases.