感谢 cmets 关于我的问题,我做了一些研究并得出以下发现。
使用多个数据库会导致在使用迁移时创建表django_migrations。正如Kamil Niski 的评论所解释的那样,没有选项只能在一张表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 使用默认数据库。
要执行的操作:
应用所有迁移: admin、auth、contenttypes、sessions
运行迁移:
正在应用 contenttypes.0001_initial... 好的
正在应用 auth.0001_initial... OK
正在应用 admin.0001_initial... OK
正在应用 admin.0002_logentry_remove_auto_add... OK
正在应用 admin.0003_logentry_add_action_flag_choices... OK
正在应用 contenttypes.0002_remove_content_type_name... 确定
正在应用 auth.0002_alter_permission_name_max_length... OK
正在应用 auth.0003_alter_user_email_max_length... OK
正在应用 auth.0004_alter_user_username_opts... 确定
正在应用 auth.0005_alter_user_last_login_null... OK
正在应用 auth.0006_require_contenttypes_0002... 确定
应用 auth.0007_alter_validators_add_error_messages... 好的
正在应用 auth.0008_alter_user_username_max_length... OK
正在应用 auth.0009_alter_user_last_name_max_length... OK
正在应用 auth.0010_alter_group_name_max_length... OK
正在应用 auth.0011_update_proxy_permissions... 好的
正在应用 session.0001_initial... OK
Django 已将所有迁移应用到默认数据库:
1 内容类型 0001_initial 2019-11-13 16:51:04.767382
2 auth 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 auth 0003_alter_u 2019-11-13 16:51:04.923902
9 认证 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 认证 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
在运行迁移之前,我们在 bar 应用程序中创建 routers.py:
类 BarRouter(object):
def db_for_read(自我,模型,**提示):
如果 model._meta.app_label == 'bar':
返回“远程”
返回无
def db_for_write(自我,模型,**提示):
如果 model._meta.app_label == 'bar':
返回“远程”
返回无
def allow_relation(self, obj1, obj2, **hints):
返回无
def allow_migrate(self, db, app_label, model_name=None, **hints):
如果 app_label == 'bar':
返回 db == '远程'
如果 db == '远程':
返回假
返回无
并在foo/settings.py注册:
DATABASE_ROUTERS = ['foo.bar.routers.BarRouter']
现在最简单的方法是将bar 的迁移运行到remote 数据库中:
python manage.py migrate bar --database=remote
要执行的操作:
应用所有迁移:栏
运行迁移:
正在应用 bar.0001_initial... OK
迁移已应用于remote 数据库:
1 bar 0001_initial 2019-11-13 17:32:39.701784
当我们运行时:
python manage.py runserver
将发出以下警告:
您有 1 个未应用的迁移。您的项目可能无法正常工作
直到您为应用应用迁移:bar。
运行“python manage.py migrate”以应用它们。
不过,一切似乎都很好。但是,收到此警告并不令人满意。
正确的方法是按照answer 中的建议为每个数据库运行所有迁移。
看起来像这样:
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 中所指定。 remote 数据库中的表 django_migrations 也将包含这些迁移的记录。
这是一个很长的阅读,但我希望它能对这个问题有所了解,在我看来,官方documentation中没有彻底解释的问题。