【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):

動きを翻訳してみるとこんな感じです。

  1. company/viewsの7行目にあるInquiryFormを調べるため、company/forms.pyを読みに行く。
  2. forms.pyの45行目にあるCompanyCreateFormを読みに行く。
  3. で、読もうとしたら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つです。

  1. blankを外す ※エラーの元となる構成を積み込まない
  2. 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のマイグレーションは行末に【;】を付けるから目が違和感を察知しなかったんだろうなぁ。

反省です。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください