【发布时间】:2019-06-23 21:46:20
【问题描述】:
设置:一个具有两种模式的 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 表?经过大量谷歌搜索后,我看到了许多关于使用数据库路由器的建议。 “其他”模式必须与“默认”模式具有所有相同的表,因此在这种情况下路由器将无济于事。
在“默认”上运行迁移然后在“其他”上运行迁移后,我尝试执行 SQL DELETE FROM django_migrations;这仅适用于新数据库上的第一次迁移,任何后续迁移尝试都会导致错误,因为 Django 尝试应用已应用的迁移并引发 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 表的问题:每个模式应该有一个,这当然很有意义。
所以这让我认为 Django 在尝试迁移“其他”模式时必须查看“默认”模式中的django_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...
【问题讨论】:
标签: python django postgresql migration multiple-schema