Django:The Model名 could not be changed because the data didn't validate.エラーの原因と対策

Django:The Model名 could not be changed because the data didn't validate.エラーの原因と対策

これは私がCRUD作成の一番最初に苦しめられたエラーです。

POSTされた値のカラム名がForm / ModelFormと合致していないときに発生します。
エラー発生原は様々ですが、私の場合は下の組合せが原因でした。

  1. Models.py 内で【models.DateField(null=True, default=None)】としたフィールドに対し何も入れずにPOSTした。
  2. Models.py 内で【models.IntegerField(null=True, default=None)】としたフィールドに対し何も入れずにPOSTした。
  3. Models.py 内で【RegexValidator(regex=r'^[0-9]+$')】としたフィールドに対し何も入れずにPOSTした。
  4. POSTしたリレーションカラム名がModel内の名称と違っていた

POSTされた値が文字列ではない時やリレーションを張っているカラムが存在する時、このエラーの発生率は高まります。

なにも記載しないでPOSTした場合、[ ’’ ]や[ 'None' ] がPOSTされている

Validateのエラーはこのような空データが原因となっている事が多いようです。
回避する手段については以前も少し触れましたが2つあります。

  1. Form / ModelFormのバリデーションを使わない。
  2. POSTされた[ '' ] や [ 'None ] を置換してからForm / ModelFormのバリデーションにかける

最適解としては外部関数としてlibrary.pyなどに下記コードを登録し利用したうえでバリデーションに掛ける事です。

def BlankChanger(data):
    #''や’None’でPOSTされた値をNoneに置き換える
    copy_dict = data.copy()
    for cd in copy_dict:
        if (cd == '')or(cd == 'None'):
           cd = None
    return copy_dict

上に記載した私が経験した原因の1~3はこれでクリアできます。

POSTしたリレーションカラム名ってなに?

from django.db import models
from accounts.models import CustomUser

class Customerdatas(models.Model):

    customer = models.ForeignKey(CustomUser,  on_delete=models.CASCADE, verbose_name='ユーザーID')
    birthday = models.DateField(verbose_name="生年月日", blank=False, auto_now=False, default=None)
    lasteducation = models.CharField(verbose_name="最終学歴", max_length=100, blank=True, null=True, default=None)
    graduationdate = models.DateField(verbose_name='卒業年月', blank=True, null=True, default=None)
    prmessaeg = models.TextField(verbose_name='PR文', blank=True, null=True, default=None)
    created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)

    class Meta:
        verbose_name_plural = 'Customerdatas'

        def __str__(self):
            return self.CustomUser.last_name + ' ' + self.CustomUser.first_name

この6行目【customer = models.ForeignKey(CustomUser, on_delete=models.CASCADE...)】がリレーションのテーブルです。このリレーションは今『1対多』で組んでいます。

注目はcustomer_idではなくcustomerで登録している事です。

LaravelではSQLテーブルの姿をそのまま記載するのでカラムの呼び出しは【customer_id】とすることが基本ですが、Djangoは [ _id ]を付ける作業を勝手に行ってくれます。

customer_id = models.ForeignKey(CustomUser, on_delete=models.CASCADE, verbose_name='ユーザーID')

なので、このようにmodels.pyに書いた場合、migrationするとMySQLには【customer_id_id】というカラムが出来上がります。

ModelFormを使う場合、Modelに登録した名称が正

MySQL内のカラム名がcustomer_idになっていてもcustomeruser_idになっていても、Modelに存在していなければバリデーションエラーが発生します。

models.pyにcustomer と記載しているならTemplate.htmlでは【<imput name='customer' ...>】でPOSTしてあげましょう。

まとめ

ここら辺のエラーは多分みんなが通る道なのだろうなと思います。

慣れればなんてことはないんですけどね。

\ 最新情報をチェック /

コメントを残す

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