Djangoのマイグレーションを実行したところ、以下のように「django.db.utils.ProgrammingError: relation <DBモデル> does not exist」が出ました。
いろいろ調べた結果解決できましたので、備忘録として残します。
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedTable: relation "hhbook_user" does not exist
LINE 1: ..."auth_user_id_id", "hhbook_user"."is_enable" FROM "hhbook_us...
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
・
・(Tracebackは省略)
・
django.db.utils.ProgrammingError: relation "hhbook_user" does not exist
LINE 1: ..."auth_user_id_id", "hhbook_user"."is_enable" FROM "hhbook_us...
解決策をすぐに見たい方は、「解決方法 まとめ」まで読み飛ばしてください。
目次
解決方法 まとめ
この解決方法が有効だと思われる事象
以下の事象に当てはまれば、この記事で紹介する解決策は有効ではないでしょうか
migrate
コマンドどころか、makemigrations
やshowmigration
コマンドでも同様なエラーが発生する。- テーブルが生成済みの既存DBでは、問題なく
migrate
コマンドが実行できる。
解決方法
エラーが発生している箇所でクラス変数としてDBモデルを呼んでいないでしょうか?
もし呼んでいるようであれば、DBモデルをクラス変数ではなくコンストラクタ内で呼び出すようにすると解決できるかもしれません。
【DBモデルをクラス変数を呼んでいる例:】
DBモデルをクラス変数として呼んでいるところは、 for hhb_user in HhbookUser.objects.filter(is_enable=True):
の箇所です。
from django import forms
from home.models import HhbookUser
class PaymentForm(forms.ModelForm):
USER_LIST = []
for hhb_user in HhbookUser.objects.filter(is_enable=True):
USER_LIST.append((hhb_user.auth_user_id.id , hhb_user.get_username(20)))
USER_LIST=tuple(USER_LIST)
payment_user = forms.fields.ChoiceField(
label='購入者',
required = True,
choices= USER_LIST,
widget=forms.widgets.Select
)
【修正例:】
コンストラクタ__init__(self, *args, **kwargs):
内にDBモデルをいれました。
django import forms
from home.models import HhbookUser
class PaymentForm(forms.ModelForm):
USER_LIST = []
def __init__(self, *args, **kwargs):
super(PaymentForm, self).__init__(*args, **kwargs)
for hhb_user in HhbookUser.objects.filter(is_enable=True):
self.USER_LIST.append((hhb_user.auth_user_id.id , hhb_user.get_username(20)))
self.USER_LIST=tuple(self.USER_LIST)
self.fields['payment_user'] = forms.ChoiceField(
label='購入者',
required = True,
choices= self.USER_LIST,
widget=forms.widgets.Select
)
エラー解決までの流れ (個人用備忘録)
以下は自分が忘れないようにするために記載したもので、完全に個人用備忘録です。
まとまりがないですが、悪しからず。
テスト環境で「coverage test」を実行したらエラーが発生
開発環境では動いていた系をテスト環境で構築して、「coverage test」を実行したところ、、、下記エラーが発生。
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedTable: relation "hhbook_user" does not exist
LINE 1: ..."auth_user_id_id", "hhbook_user"."is_enable" FROM "hhbook_us...
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
・
・(Tracebackは省略)
・
django.db.utils.ProgrammingError: relation "hhbook_user" does not exist
LINE 1: ..."auth_user_id_id", "hhbook_user"."is_enable" FROM "hhbook_us...
「relation "hhbook_user" does not exist
」と言っており、DBモデル?テーブル?がないと言っている。
実際にテスト環境では"hhbook_user"
というテーブルは生成されていなかった。
テーブルがうまく生成されていないということは、Djangoのマイグレーションに問題があるのではないかと考え、テスト環境で「manage.py migrate」を実行してみると、上記エラーと同じものがでた。
「coverage test」が問題ではなく、マイグレーションに問題があると分かった。
マイグレーション系のコマンドをいろいろ試してみる
「manage.py migrate」の実行エラーなら、再度マイグレーションファイルを作成すればいいのかと考え、「manage.py makemigrations」を実行してみたが、同じエラーが出た。
いろいろ調べた結果、以下のコマンドでそもそもエラーが出ていることが分かった。
- manage.py migrate
- manage.py makemigrations
- manage.py showmigration
でも、開発環境ではマイグレーションは問題なく動いているし、、、
テーブルがないのが原因みたいだが、テーブルを作るマイグレーションで失敗するとは、、、どうすればいいのだ?
とりあえず、エラー内容をググってみることにした。
エラー内容をググってみた
「django.db.utils.ProgrammingError: relation <DBモデル> does not exist」でググってみた。
- 【Django】 relation does not exist が発生してしまう。 | teratail
- このブログでは、「manage.py makemigrations」コマンドは実行できているので、エラー事象があっていない。
- herokuの仕様上の問題のようで、解決方法はローカルで「make migration」を実行すればよいとのことだが[1]、自分の環境ではローカルでも同じエラーが発生した。
- django.db.utils.ProgrammingError: relation "auth_user" does not exist の解決 | teratail
- このブログでは、「manage.py makemigrations」コマンドは実行できているので、エラー事象があっていない。
- 解決方法はPostgreSQL,Django,Pythonの環境を全て再導入すればよいとのことだが[2]、自分の環境では再構築しなおしても改善されず。
- Djangoの初回マイグレーション時に relation "auth_user" does not exist というエラーが発生する場合 | Yura YuLife
- 解決方法は先にauthのマイグレーションを行えばよいとのことだが[3]、authのみマイグレーションしようとしても同じエラーが発生。
- django.db.utils.ProgrammingError: relation “bot_trade” does not exist | stack overflow
- Django Rest Framework "django.db.utils.ProgrammingError:relation" patient "does not exist" | stackoverrun
- Users and Roles for DJango App running with Postgres dB in DO droplet | Community
エラー内容でググると、いろいろ出てきたが、、、すべて解決できず。migrate
コマンドで発生するエラーについては多くあったが、makemigrations
やshowmigration
コマンドで発生している事例は見かけなかった。
暫定解決? pathを無効にすればいける!
いろいろいじっていたら、urls.pyのurlpatterns
を[]
にすればマイグレーションがうまくいくことが分かった。makemigrations
やshowmigration
コマンドの実行もうまくいった。
マイグレーションが実行でき、テーブルが作成できるので、その後urlpatterns
を元に戻してやれば問題なく動くことが確認できた!
【urls.py】
urlpatterns = [
#path('', include('home.urls')),
#path('hhbook/', include('hhbook.urls')),
#path('admin/', admin.site.urls),
]
- homeやhhbookは自分で作ったアプリ
- admin.site.urlsはDjangoのログイン機能
とりあえず暫定解決はできそうだ!!!
だけど、テスト環境を構築するたびにurls.pyのurlpatterns
を[]
にするのはめんどい。
本質的な解決にはなっていないので、もうちょい調べることにする。
上のコードでは、すべてのアプリをコメントアウトしているが、Djangoのログイン機能のみ有効にしてマイグレーションしてみたら、成功した。
つまり、自分のアプリがバグっている!ということだ笑
もう一度、エラー内容をよく見てみる
エラー内容の詳細(Traceback)
File "/code/hhbook/urls.py", line 3, in <module>
from . import views
File "/code/hhbook/views.py", line 5, in <module>
from .forms import PaymentForm,SearchForm
File "/code/hhbook/forms.py", line 7, in <module>
class PaymentForm(forms.ModelForm):
File "/code/hhbook/forms.py", line 17, in PaymentForm
for hhb_user in HhbookUser.objects.filter(is_enable=True):
PaymentFormのとこで、DBモデル"hhb_user"を読んでいて、それが異常の原因となっているようだ。
PaymentFormを見てみる。
from django import forms
from home.models import HhbookUser
class PaymentForm(forms.ModelForm):
USER_LIST = []
for hhb_user in HhbookUser.objects.filter(is_enable=True):
USER_LIST.append((hhb_user.auth_user_id.id , hhb_user.get_username(20)))
USER_LIST=tuple(USER_LIST)
payment_user = forms.fields.ChoiceField(
label='購入者',
required = True,
choices= USER_LIST,
widget=forms.widgets.Select
)
なんと、HhbookUser.objects.filter()
でPaymentFormクラスのクラス変数として、DBモデル(インスタンス変数)を呼んでいる!
これが原因ではないだろうか。。。。バグやんn
DBモデルをクラス変数ではなく、コンストラクタで呼ぶようにする
クラス変数としてインスタンス変数を呼んでいるのが原因なら、インスタンス変数をコンストラクタに入れればいい!
ということで、先ほどのPaymentFormを以下のように修正した。
django import forms
from home.models import HhbookUser
class PaymentForm(forms.ModelForm):
USER_LIST = []
def __init__(self, *args, **kwargs):
super(PaymentForm, self).__init__(*args, **kwargs)
for hhb_user in HhbookUser.objects.filter(is_enable=True):
self.USER_LIST.append((hhb_user.auth_user_id.id , hhb_user.get_username(20)))
self.USER_LIST=tuple(self.USER_LIST)
self.fields['payment_user'] = forms.ChoiceField(
label='購入者',
required = True,
choices= self.USER_LIST,
widget=forms.widgets.Select
)
これでマイグレーションを実行してみたらうまくいった!makemigrations
やshowmigration
コマンドの実行もうまくいった。
自分のアプリのバグが原因でした
「django.db.utils.ProgrammingError: relation <DBモデル> does not exist」エラーの原因はアプリのクラス変数でDBモデルのインスタンス変数を呼んでいることでした。
Tracebackログを見ると、マイグレーション実行時にpathからアプリが使用するDBモデルを確認しているようです。
開発環境ではすでにマイグレーション済みのDBがあり、DBモデルがインスタンス化できるためこのエラーが発生しなかったようです。一方、テスト環境ではDBは空の状態のためDBモデルがインスタンス化できずこのエラーが出たのだと思います。
戒め
エラー内容をググるだけでなく、きちんとエラー発生個所に問題ないか確認しよう!!!
参考
[1] 【Django】 relation does not exist が発生してしまう。 | teratail
[2] django.db.utils.ProgrammingError: relation "auth_user" does not exist の解決 | teratail
[3] Djangoの初回マイグレーション時に relation "auth_user" does not exist というエラーが発生する場合 | Yura YuLife
[4] django.db.utils.ProgrammingError: relation “bot_trade” does not exist | stack overflow
[5] Django Rest Framework "django.db.utils.ProgrammingError:relation" patient "does not exist" | stackoverrun
[6] Users and Roles for DJango App running with Postgres dB in DO droplet | Community
[7] Django Model instance value in ModelForm constructor | stackoverflow
[8] django forms - overriding constructor for changing field type depending by input | stackoverflow
[9] DjangoのFormに初期値を設定する方法 | Freelance Note
広告
Djangoをやるなら以下の書籍がオススメです。
DjangoでWebアプリを開発するときの要点が分かりやすくまとめられています。
ConoHa VPS
は初期費用不要で月に数百円で利用できる仮想サーバのサービスです。以下のような方には非常にオススメのサービスとなっています!
- 勉強がてらLinuxの環境をちょっと触ってみたい
⇒管理者権限が実行可能なLinuxサーバ環境が構築可能です! - スモールスタートでサービスを提供して、うまくいったら規模をスケールアップしたい
⇒後からメモリサイズやCPU数などのスケールアップ/スケールダウン可能です! - AWSやGCPなどのクラウドサービスは高いので、もっと安くサーバ構築したい
⇒初期費用なし、月数百円(1時間単位も可)で利用可能です!
以上!
コメント