【Django】django.core.exceptions.FieldError: Unknown field(s) () specified for
【Django】django.core.exceptions.FieldError: Unknown field(s) () specified for
なかなか悩みました。直訳すれば「知らないフィールド操作しようとしてるよ」って事なのです。
でもそこはDjango初心者、怪しい所を見ていても気づかないというね。
と言う事で、今後の為の整理整頓です。
まずエラーが出たらエラー直前の動きを確認する
どういうルートでプログラムが動いたかを確認すれば『修正場所』が解ります。
今回のエラー発生直前の流れはこんな感じでした。
File "/code/company/views.py", line 7, in <module> from .forms import InquiryForm File "/code/company/forms.py", line 45, in <module> class CompanyCreateForm(forms.ModelForm):
動きを翻訳してみるとこんな感じです。
- company/viewsの7行目にあるInquiryFormを調べるため、company/forms.pyを読みに行く。
- forms.pyの45行目にあるCompanyCreateFormを読みに行く。
- で、読もうとしたらCompanyCreateFormに書いてあるフィールドが無いんですけど...。
と言う事は、怪しいのはテーブル構成を管理してるModelsって事になります。
記載していた誤ったmodels.py と正しいmodels.py
まずは正しいものから。
from django.db import models
class Company(models.Model):
"""企業情報モデル"""
name = models.CharField(verbose_name='企業名', max_length=200, blank=False)
postal_code = models.CharField(verbose_name='郵便番号', max_length=7, blank=False)
prefecture = models.CharField(verbose_name='県名', max_length=10, blank=True)
municipalities = models.CharField(verbose_name='市町村', max_length=30, blank=True)
details = models.CharField(verbose_name='番地詳細', max_length=50, blank=True)
buildings = models.CharField(verbose_name='建物名', max_length=150, blank=True)
tel_number = models.CharField(verbose_name='電話番号', max_length=15, blank=False)
fax_number = models.CharField(verbose_name='FAX番号', max_length=15, blank=True)
email = models.EmailField(verbose_name='代表メール', blank=True)
website = models.URLField(verbose_name='ホームページ', blank=True)
created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)
class Meta:
verbose_name_plural = 'Company'
def __str__(self):
return self.name
こちら、間違えていたものです。
from django.db import models
class Company(models.Model):
"""企業情報モデル"""
name = models.CharField(verbose_name='企業名', max_length=200, blank=False),
postal_code = models.CharField(verbose_name='郵便番号', max_length=7, blank=False),
prefecture = models.CharField(verbose_name='県名', max_length=10, blank=True),
municipalities = models.CharField(verbose_name='市町村', max_length=30, blank=True),
details = models.CharField(verbose_name='番地詳細', max_length=50, blank=True),
buildings = models.CharField(verbose_name='建物名', max_length=150, blank=True),
tel_number = models.CharField(verbose_name='電話番号', max_length=15,blank=False),
fax_number = models.CharField(verbose_name='FAX番号', max_length=15, blank=True),
email = models.EmailField(verbose_name='代表メール', blank=True)
website = models.URLField(verbose_name='ホームページ', blank=True)
created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)
class Meta:
verbose_name_plural = 'Company'
def __str__(self):
return self.name
NG箇所は各行最後の【 , (カンマ)】。こいつがあったからテーブル構成がおかしくなってたんですね。
マイグレーション用ファイルを作成する
python manage.py makemigrations
そしてマイグレーション実行。
python manage.py migrate
ん?またエラーが出ました。
You are trying to add a non-nullable field '' to company without a default; we can't do that (the database needs something to populate existing rows).
NULLを許可してないのに blank=False するなと怒られている?
name = models.CharField(verbose_name='企業名', max_length=200, blank=False)
どうやらこいつがNGの様子。Laravelのマイグレーションって空のテーブルを作る形だったから全く意識してなかったけどDjangoではここら辺しっかりしてないとダメみたいです。
Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.py Select an option:
1を選択するとPython が起動してゴニョゴニョできます。
2を選択するとマイグレーションが終了します。
You are trying to add a non-nullable field '' to company without a defaultの解決方法
方法は2つです。
- blankを外す ※エラーの元となる構成を積み込まない
- default値を設定する
defaultを設定する場合、次のように書きます。
(前略) prefecture = models.CharField(verbose_name='県名', max_length=10, default='新潟県') municipalities = models.CharField(verbose_name='市町村', max_length=30, null=True)
defult='ほげ' でデフォルトに固定値が入り、null=TrueとするとデフォルトにNULLが設定されます。
デフォルトを構成して python manage.py migrate すればテーブル作成完了です。
郵便番号とか電話番号のバリデーションで数値以外を記載できない様にする
postal_code_regex = RegexValidator(regex=r'^[0-9]+$', message = ("Postal Code must be entered in the format: '1234567'. Up to 7 digits allowed."))
postal_code = models.CharField(validators=[postal_code_regex], max_length=7, verbose_name='郵便番号', null=True)
こんな形で構成してあげるとValidationを一緒に記載できるそうです。
まとめ
models.pyのカンマ、なんで気付かなかったのか...。
Laravelのマイグレーションは行末に【;】を付けるから目が違和感を察知しなかったんだろうなぁ。
反省です。


