セットアップ: 'default' と 'other' の 2 つのスキーマを持つ 1 つの 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 スキーマごとに 1 つありますか? django_migrations
それとも、プロジェクトごとに 1 つのテーブルしかありませんか? 多くのグーグル検索の後、データベースルーターの使用に関する多くの提案を見ました。「他の」スキーマには、「デフォルト」スキーマと同じテーブルがすべて含まれている必要があるため、この場合、ルーターは役に立ちません。
DELETE FROM django_migrations
「デフォルト」で移行を実行し、「その他」で移行を実行した後、SQL を実行しようとしました。これは、新しいデータベースでの最初の移行に対してのみ機能し、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
ます。スキーマごとに1つある必要があり、これはもちろん完全に理にかなっています。
django_migrations
したがって、これは、「他の」スキーマを移行しようとするときに、Django が「デフォルト」スキーマのテーブルを参照している必要があるため、「適用する移行が存在しない」と判断することにつながります。私はこれを解決しようとし続けます。両方のスキーマで移行を機能させる方法がまだわからないので、ポインタは大いに役立ちます。
アップデート
これを回答として書いたのですが、このソリューションはローカルでしか機能しなかったため、代わりに更新として追加しました。
しばらく構成を見つめた後、DATABASES
私が目にしていた問題の原因をようやく理解しました。search_path
次のように、各オプションにコンマ区切りのリストを提供しました。
DATABASES = {
'default': {
...
'OPTIONS': {
'options': '-c search_path=django,default',
},
...
},
'other': {
...
'OPTIONS': {
'options': '-c search_path=other,default',
},
...
}
}
ここで何が起こっているかについての私の解釈:新しいデータベースで実行すると、Djangoは「デフォルト」スキーマにテーブルpy manage.py migrate
がないことを確認し、テーブルを作成してから、移行を適用するときにデータを入力します。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...