Django Postgres 多模式迁移:"No migrations to apply"
Django Postgres Multiple Schema Migrations: "No migrations to apply"
设置:一个具有两个模式的 Postgres 数据库:'default' 和 'other'。使用:
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
:按预期工作并且 'default' 架构已正确迁移。
py manage.py migrate --database=other
结果:No migrations to apply.
奇怪的是,以相反的顺序执行这些步骤(再次在新数据库上)有效:
py manage.py migrate --database=other
:按预期工作并且 'other' 架构已正确迁移。
py manage.py migrate
结果:按预期工作并且 'default' 架构已正确迁移。
我怀疑这与 django_migrations
table 有关。我不太了解这个 table,每个 Postgres 模式都有一个吗?或者每个项目只有一个 django_migrations
table?经过大量谷歌搜索后,我看到了很多关于使用数据库路由器的建议。 'other' 架构必须具有与 'default' 架构完全相同的 table,因此在这种情况下路由器将无济于事。
我尝试在 'default' 运行ning 迁移之后执行 SQL DELETE FROM django_migrations
,然后在 'other' 执行 运行ning 迁移;这仅适用于新数据库上的第一次迁移,任何后续迁移尝试都会导致错误,因为 Django 会尝试应用已经应用的迁移并引发 django.db.utils.ProgrammingError: relation "<relation>" already exists
.
我也试过使用 django.db.migrations.recorder.MigrationRecorder
class 刷新迁移 'default' 和 'other' 数据库之间的迁移 table,同样没有运气.
此外,我能够让我的测试套件达到 运行 的唯一方法是将 'other' 设置为 'default' 的依赖项,以利用迁移 'other' 在 'default' 工作之前。
我不知道为什么会这样,我确定我遗漏了什么。
更新
采取与前面提到的相同的步骤:
py manage.py migrate
:按预期工作并且 'default' 架构已正确迁移。
py manage.py migrate --database=other
结果:No migrations to apply.
在 pgAdmin 中进行一些挖掘之后,我 运行 以下 SQL
SET search_path TO default
SELECT * FROM django_migrations
这按预期返回了 table 应用迁移。然后运行宁以下SQL
SET search_path TO other
SELECT * FROM django_migrations
我收到一条错误消息,指出关系 "django_migrations" 不存在。所以这回答了我关于 django_migrations
table 的问题:每个模式应该有一个,这当然很有意义。
所以这让我认为 Django 在尝试迁移 'other' 模式时必须查看 'default' 模式中的 django_migrations
table 并因此看到有 "no migrations to apply"。我会继续努力解决这个问题,任何指示都会有很长的路要走,因为我仍然不确定如何让迁移在两个模式上工作。
更新
我把它写成一个答案,但这个解决方案只在本地有效,所以我把它添加为更新。
盯着 DATABASES
配置一段时间后,我终于明白是什么导致了我所看到的问题。我为每个 search_path
选项提供了一个逗号分隔的列表,如下所示:
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=django,default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other,default',
},
...
}
}
我对这里发生的事情的解释:当 运行ning py manage.py migrate
在新数据库上时,Django 会发现 django_migrations
table 'default' 架构,创建一个,然后在应用迁移时填充它。然后当我 运行 py manage.py migrate --database=other
它会在 'other' 中寻找 django_migrations
,找不到它然后它必须在 'default' 中寻找,因为它是下一个地方查看搜索路径。由于 django_migrations
已经存在于 'default' 模式中,Django 将使用此 table 然后看到有 "no migrations to apply"。可能我说的不完全准确,如有明显错误请指正。
像这样更改 DATABASES
配置中的搜索路径:
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other',
},
...
}
}
导致两个模式都在我的本地环境中成功迁移。但是,当在 TravisCI 或 Heroku 上迁移 运行 时,这不起作用。两者都在 'default' 或 'other':
迁移时给出此错误
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...
我的问题的解决方案分为两部分。
让迁移在 TravisCI 上工作
发现 GitHub 令人难以置信的回购搜索功能后,我在任何 .travis.yml
文件中搜索了 CREATE SCHEMA <schema_name>
的任何用法。
我将 .travis.yml
文件的 before_script
中的这两行从
更改为
- psql -c "CREATE DATABASE travisci;" -U postgres
- psql -c "CREATE SCHEMA other;" -U postgres
到
- psql -c "CREATE DATABASE travisci;" -U postgres
- psql -c "CREATE SCHEMA other;" -d travisci -U postgres
添加 -d travisci
参数导致两个模式都正确迁移。
让迁移在 Heroku 上工作
我一直在使用此命令访问我的 Heroku 应用程序的 SQL 客户端:
heroku pg:psql -a <app_name>
我应该很清楚为什么这行不通。每个 Heroku 应用程序可以有多个数据库,我没有指定数据库名称。使用此命令有效:
heroku pg:psql <database_name> -a <app_name>
也可以使用 pgAdmin 创建模式。
设置:一个具有两个模式的 Postgres 数据库:'default' 和 'other'。使用:
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
:按预期工作并且 'default' 架构已正确迁移。py manage.py migrate --database=other
结果:No migrations to apply.
奇怪的是,以相反的顺序执行这些步骤(再次在新数据库上)有效:
py manage.py migrate --database=other
:按预期工作并且 'other' 架构已正确迁移。py manage.py migrate
结果:按预期工作并且 'default' 架构已正确迁移。
我怀疑这与 django_migrations
table 有关。我不太了解这个 table,每个 Postgres 模式都有一个吗?或者每个项目只有一个 django_migrations
table?经过大量谷歌搜索后,我看到了很多关于使用数据库路由器的建议。 'other' 架构必须具有与 'default' 架构完全相同的 table,因此在这种情况下路由器将无济于事。
我尝试在 'default' 运行ning 迁移之后执行 SQL DELETE FROM django_migrations
,然后在 'other' 执行 运行ning 迁移;这仅适用于新数据库上的第一次迁移,任何后续迁移尝试都会导致错误,因为 Django 会尝试应用已经应用的迁移并引发 django.db.utils.ProgrammingError: relation "<relation>" already exists
.
我也试过使用 django.db.migrations.recorder.MigrationRecorder
class 刷新迁移 'default' 和 'other' 数据库之间的迁移 table,同样没有运气.
此外,我能够让我的测试套件达到 运行 的唯一方法是将 'other' 设置为 'default' 的依赖项,以利用迁移 'other' 在 'default' 工作之前。
我不知道为什么会这样,我确定我遗漏了什么。
更新
采取与前面提到的相同的步骤:
py manage.py migrate
:按预期工作并且 'default' 架构已正确迁移。py manage.py migrate --database=other
结果:No migrations to apply.
在 pgAdmin 中进行一些挖掘之后,我 运行 以下 SQL
SET search_path TO default
SELECT * FROM django_migrations
这按预期返回了 table 应用迁移。然后运行宁以下SQL
SET search_path TO other
SELECT * FROM django_migrations
我收到一条错误消息,指出关系 "django_migrations" 不存在。所以这回答了我关于 django_migrations
table 的问题:每个模式应该有一个,这当然很有意义。
所以这让我认为 Django 在尝试迁移 'other' 模式时必须查看 'default' 模式中的 django_migrations
table 并因此看到有 "no migrations to apply"。我会继续努力解决这个问题,任何指示都会有很长的路要走,因为我仍然不确定如何让迁移在两个模式上工作。
更新
我把它写成一个答案,但这个解决方案只在本地有效,所以我把它添加为更新。
盯着 DATABASES
配置一段时间后,我终于明白是什么导致了我所看到的问题。我为每个 search_path
选项提供了一个逗号分隔的列表,如下所示:
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=django,default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other,default',
},
...
}
}
我对这里发生的事情的解释:当 运行ning py manage.py migrate
在新数据库上时,Django 会发现 django_migrations
table 'default' 架构,创建一个,然后在应用迁移时填充它。然后当我 运行 py manage.py migrate --database=other
它会在 'other' 中寻找 django_migrations
,找不到它然后它必须在 'default' 中寻找,因为它是下一个地方查看搜索路径。由于 django_migrations
已经存在于 'default' 模式中,Django 将使用此 table 然后看到有 "no migrations to apply"。可能我说的不完全准确,如有明显错误请指正。
像这样更改 DATABASES
配置中的搜索路径:
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other',
},
...
}
}
导致两个模式都在我的本地环境中成功迁移。但是,当在 TravisCI 或 Heroku 上迁移 运行 时,这不起作用。两者都在 'default' 或 'other':
迁移时给出此错误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...
我的问题的解决方案分为两部分。
让迁移在 TravisCI 上工作
发现 GitHub 令人难以置信的回购搜索功能后,我在任何 .travis.yml
文件中搜索了 CREATE SCHEMA <schema_name>
的任何用法。
我将 .travis.yml
文件的 before_script
中的这两行从
- psql -c "CREATE DATABASE travisci;" -U postgres
- psql -c "CREATE SCHEMA other;" -U postgres
到
- psql -c "CREATE DATABASE travisci;" -U postgres
- psql -c "CREATE SCHEMA other;" -d travisci -U postgres
添加 -d travisci
参数导致两个模式都正确迁移。
让迁移在 Heroku 上工作
我一直在使用此命令访问我的 Heroku 应用程序的 SQL 客户端:
heroku pg:psql -a <app_name>
我应该很清楚为什么这行不通。每个 Heroku 应用程序可以有多个数据库,我没有指定数据库名称。使用此命令有效:
heroku pg:psql <database_name> -a <app_name>
也可以使用 pgAdmin 创建模式。