设置:一个具有两种模式的 Postgres 数据库:“默认”和“其他”。使用:
Django==2.0.10
psycopg2-binary==2.7.7
(生产中没有二进制版本)
我的数据库配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
'options': '-c search_path=django,default',
},
...
'TEST': {
'NAME': 'default',
'DEPENDENCIES': ['other'],
},
'ATOMIC_REQUESTS': True,
},
'other': {
'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
'options': '-c search_path=other,default',
},
...
'TEST': {
'NAME': 'other',
'DEPENDENCIES': [],
},
'ATOMIC_REQUESTS': True,
}
}
对新数据库采取的步骤:
py manage.py migrate
:按预期工作,并且“默认”架构已正确迁移。py manage.py migrate --database=other
结果是:No migrations to apply.
奇怪的是,以相反的顺序采取这些步骤(再次,在一个新的数据库上)有效:
py manage.py migrate --database=other
:按预期工作,并且“其他”架构已正确迁移。py manage.py migrate
结果:按预期工作,并且“默认”架构已正确迁移。
我怀疑这与django_migrations
桌子有关。我对这张表不太了解,每个 Postgres 模式都有一个吗?还是django_migrations
每个项目只有一张桌子?经过大量谷歌搜索后,我看到了许多关于使用数据库路由器的建议。“其他”模式必须与“默认”模式具有所有相同的表,因此在这种情况下路由器将无济于事。
DELETE FROM django_migrations
在“默认”上运行迁移然后在“其他”上运行迁移后,我尝试执行 SQL ;这仅适用于新数据库上的第一次迁移,任何后续迁移尝试都会导致错误,因为 Django 尝试应用已应用的迁移并 raises django.db.utils.ProgrammingError: relation "<relation>" already exists
。
我还尝试过使用django.db.migrations.recorder.MigrationRecorder
该类来在迁移“默认”和“其他”数据库之间刷新迁移表,再次没有运气。
此外,我能够让我的测试套件运行的唯一方法是将“其他”设置为“默认”的依赖项,以利用在“默认”之前迁移“其他”有效的奇怪事实。
我不知道为什么会这样,我确定我缺少一些东西。
更新
采取与前面提到的相同的步骤:
py manage.py migrate
:按预期工作,并且“默认”架构已正确迁移。py manage.py migrate --database=other
结果是:No migrations to apply.
在 pgAdmin 中进行了一些挖掘之后,我运行了以下 SQL
SET search_path TO default
SELECT * FROM django_migrations
这按预期返回了应用迁移表。然后运行以下SQL
SET search_path TO other
SELECT * FROM django_migrations
我得到一个错误,说关系“django_migrations”不存在。所以这回答了我关于django_migrations
表的问题:每个模式应该有一个,这当然很有意义。
因此,这使我认为 Djangodjango_migrations
在尝试迁移“其他”模式时必须从“默认”模式查看表,因此看到“没有要应用的迁移”。我将继续尝试解决这个问题,任何指针都会有很长的路要走,因为我仍然不确定如何让迁移在两个模式上工作。
更新
我已将其写为答案,但此解决方案仅在本地有效,因此我将其添加为更新。
在盯着DATABASES
配置看了一会儿后,我终于明白是什么导致了我看到的问题。我为每个search_path
选项提供了一个逗号分隔的列表,如下所示:
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=django,default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other,default',
},
...
}
}
我对这里发生的事情的解释:在py manage.py migrate
新数据库上运行时,Django 会看到“默认”模式中没有django_migrations
表,创建一个表,然后在应用迁移时填充它。然后,当我运行py manage.py migrate --database=other
它时,它会在“其他”中django_migrations
查找,找不到它,然后它必须在“默认”中查找,因为它是在搜索路径中查找的下一个位置。正如django_migrations
“默认”模式中已经存在的那样,Django 将使用此表,然后看到“没有要应用的迁移”。在这里我可能不完全准确,如果我说了什么明显错误的地方,请纠正我。
更改DATABASES
配置中的搜索路径,如下所示:
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other',
},
...
}
}
导致两种模式都在我的本地环境中成功迁移。但是,当迁移在 TravisCI 或 Heroku 上运行时,这不起作用。在迁移“默认”或“其他”时,两者都会出现此错误:
Traceback (most recent call last):
File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
return self.cursor.execute(sql)
psycopg2.ProgrammingError: no schema has been selected to create in
LINE 1: CREATE TABLE "django_migrations" ("id" serial NOT NULL PRIMA...