Validationとは?
- FORMからPOSTされたデータが正しい形式か検証(Validate)する機能である。
- 例えばメールアドレスのデータがxxxxxx@xxxx.xxの形式かチェックすることを指す
- Djangoには様々なValidation機能が存在する。
- もちろんカスタマイズして利用することも可能
ValidationErrorについて
- ValidationErrorはエラー発生時に実行されるクラス
- FORMのValidationはいくつかのステップで行われている。
- ステップはフォームとフィールドの検証を参照
- ValidationErrorを発生させることで、FORMはValidation失敗を検知してエラーを返す。
Validationの動作検証方法
Validationの検証のためにFORM、Templateなどを全て用意する必要はない。manage.py shellを使用すれば良い。
なお、今回使用するModelとFormは以下とする。
models.py
from django.db import models
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')
forms.py
from django import forms
from .models import Post
class CmsCreateViewForm(forms.ModelForm):
class Meta:
model = Post
fields = (
'title',
'content',
)
ここからは検証方法。
まずはshellを起動。
python manage.py shell
次にformsのインポートして、formsのクラスをインスタンス化する。
ここのdataの値を変えることでValidationチェックが可能
>>> from app.forms import CmsCreateViewForm
>>> data = {'title': 'shell', 'content': 'shell'}
>>> f = CmsCreateViewForm(data)
is_valid()でValidationを実行。Falseなので失敗していることがわかる。
>>> f.is_valid()
False
erorrsやnon_field_errorsで何のエラーか分かる。
>>> f.errors
{'__all__': ['Title length is short.'], 'title': ['Title length is short.']}
>>> f.non_field_errors
<bound method BaseForm.non_field_errors of <CmsCreateViewForm bound=True, valid=False, fields=(title;content;image)>>
エラーについて詳しくは以下の記事を参照。
[Django] Formのエラーをtemplateに表示する方法のまとめ。errorsとnon_filed_errorsの違いについて
FormClassでValidation
ModelClassやFormClassは上記のものを一部流用する。
Formで発生させる箇所は大きく分けて2つ。
- FieldでValidatorを起動
- clean_{filed}()とclean()メソッドでエラーを設定
まずはFieldにValidatorを設定する場合である。
Validation用の関数を用意して設定する。validatorsにはリストで関数を指定するため、複数のValidationも設定可能。
from django import forms
from .models import Post
def check_title_length(value):
if len(value) < 10:
raise ValidationError('Title length is short.')
class CmsCreateViewForm(forms.Form):
title = forms.CharField(validators=[check_title_length])
clean{filed}()とclean()メソッドは以下のように書く。
clean{filed}()は各Fieldごとに設定可能で、errorsとnon_field_errorsのどちらのエラーに格納させるか設定可能。
cleanはField間の整合性などを取る時に使用し、エラーは必ずnon_field_errorsに入る点に注意。
from django import forms
from .models import Post
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
def clean(self):
title = self.cleaned_data.get('title')
content = self.cleaned_data.get('content')
if content.find(title):
raise forms.ValidationError('Title and content do not match.')
return self.cleaned_data
ModelClassでValidation
ModelClassやFormClassは上記のものを一部流用する。
ModelFormを使用する時にModelClassにValidationを指定することも可能。
from django.db import models
from django.core.exceptions import ValidationError
from django.utils import timezone
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')
どこのValidationを設定すべきか?
- Projectごとで決まると思っている。
- 個人的な見解としてはDjangoがValidationのStepに合わせて設定することが好ましいと考えている。
- 例えばModelFormを使用している場合はmodelクラスに設定する。
- ただModelには定義だけ書く場合にはclean_xx関数に書こうと考えている。