由于对我的问题的评论,我做了一些研究,并得出以下发现。
使用多个数据库会导致在使用django_migrations
迁移时创建表。django_migrations
正如Kamil Niski的评论所解释的,没有选项只能将迁移记录在一个表中。读取文件后,这一点很明显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将使用默认数据库。
要执行的操作:
应用所有迁移:管理员,身份验证,内容类型,会话
运行迁移:
正在应用contenttypes.0001_initial ...确定
正在应用auth.0001_initial ...确定
正在应用admin.0001_initial ...确定
正在应用admin.0002_logentry_remove_auto_add ...确定
正在应用admin.0003_logentry_add_action_flag_choices ...确定
正在应用contenttypes.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 contenttypes 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_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
在运行迁移之前,我们routers.py
在bar
应用程序内部创建:
BarRouter(object)类:
def db_for_read(self,model,** hints):
如果model._meta.app_label =='bar':
返回“远程”
不返回
def db_for_write(self,model,** hints):
如果model._meta.app_label =='bar':
返回“远程”
不返回
def allow_relation(self,obj1,obj2,**提示):
不返回
def allow_migrate(self,db,app_label,model_name = None,**提示):
如果app_label =='bar':
return db =='远程'
如果db =='remote':
返回False
不返回
并将其注册在foo/settings.py
:
DATABASE_ROUTERS = ['foo.bar.routers.BarRouter']
现在,幼稚的方法是将迁移运行bar
到remote
数据库中:
python manage.py migrate bar --database=remote
要执行的操作:
应用所有迁移: bar
运行迁移:
正在应用bar.0001_initial ...确定
迁移已应用于remote
数据库:
1 bar 0001_initial 2019-11-13 17:32:39.701784
当我们运行时:
python manage.py runserver
将发出以下警告:
您有1个未应用的迁移。您必须为应用程序应用迁移:bar,项目才能正常运行。
运行“ python manage.py migration”以应用它们。
一切似乎都正常。但是,收到此警告并不令人满意。
正确的方法是按照此答案的建议为每个数据库运行所有迁移。
它看起来像这样:
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
数据库将对这些迁移的记录了。
这是一本很长的书,但是我希望它能为我提供一些启发,使我认为这是官方文档中未详细解释的问题。