目次
Formからエラーを取得する仕組み
- DjangoのFormの値チェック(Validation)は、値のクリーニング(clean)させる時に行われる。要はPOSTされたデータを受け取り、使える形に整形中にValidationが行われる。
- またFormのValidationは複数のステップ分かれる。またこれらはカスタムやオーバーライドすることが可能
- FormクラスやModelクラスのValidator、Formクラスのclean_xxxやcleanメソッドなどでValidationを行うということである。
要はややこしい仕様がたくさんあるということ。
errorsとnon_filed_errorsの違いについて
- 一般的にはValidation違反となったらValidationErrorクラスに投げられる。
- その際に違反発生時の指定方法によって、特定Fieldのエラーと紐付けられていないエラーに分けられる。
- 特定Fieldのエラーがerrors、紐付けられていないエラーがnon_filed_errorsの2つに分けられる。
- clean_xxxやadd_error()を使用して、どのFieldのエラーか任意に設定できる。
- もちろんadd_error(None, ‘Erorr’)は特定エラーを指定しないことも可能。
errorsとnon_field_errorsへのセット方法
今回はModelForm+CreateViewを利用したパターンで説明する。
以下のサンプルModelを利用する。
class Post(models.Model):
id = models.AutoField(primary_key=True,
db_column='id')
title = models.CharField(max_length=255,
null=False,
blank=False,
db_column='title')
content = models.TextField(null=False,
blank=True,
db_column='content')
errorsに格納されるパターン
add_errorで’title’を指定しているため、Titleのフィールドのエラーとなる。
また、clean_titleと指定すると、raise forms.ValidationErrorでもtitleのエラーに格納させる。
class CmsCreateViewForm(forms.ModelForm):
class Meta:
model = Post
fields = (
'title',
'content',
)
def clean_title(self):
title = self.cleaned_data.get('title')
if len(title) <= 10:
self.add_error('title', 'Title length is short.') ★
raise forms.ValidationError('Title length is short.') ★
return title
もちろんValidatorの関数を用意したModelのValidatorでも該当Fieldのエラーとなる。
from django.db import models
from django.core.exceptions import ValidationError
def check_title_length(value):
if len(value) < 10 :
raise ValidationError('Title length is short.')
class Post(models.Model):
id = models.AutoField(primary_key=True,
db_column='id')
title = models.CharField(max_length=255,
null=False,
blank=False,
validators=[check_title_length],
db_column='title')
content = models.TextField(null=False,
blank=True,
db_column='content')
non_filed_errorに格納されるパターン。
明示的にadd_errorでNoneを指定する必要ある。
class CmsCreateViewForm(forms.ModelForm):
class Meta:
model = Post
fields = (
'title',
'content',
)
def clean_title(self):
title = self.cleaned_data.get('title')
if len(title) <= 10:
self.add_error(None, 'Title length is short.') ★
return title
templateへの表示方法
errorsの場合は、errorlistのulタグにliタグが作成させる。
以下のように書く。
{{ form.title.errors }}
ただし展開されると表示は
<ul class="errorlist">
<li>Error Message1</li>
<li>Error Message2</li>
</ul>
となる
エラーメッセージだけにしたい場合は以下のよう書く。
<ul>
{% for error in form.title.errors %}
<li>
{{ error }}
</li>
{% endfor %}
</ul>
ちなみに
{{ form.title.errors.0 }}
{{ form.title.errors.1 }}
とするとエラーメッセージだけ取得できる。
non_field_errorの場合は以下のように書く。
liタグとして出力されないのがポイントです
<ul>
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>