Django 1.7aのForm.add_errorを使ってみる
Djangoのformで複数フィールドにまたがるバリデーションをかけたい場合は、cleanメソッドに処理を書く。
例
# coding=utf-8 from django import forms from django.core.exceptions import ValidationError class PasswordConfirmForm(forms.Form): password = forms.CharField() password_confirm = forms.CharField() def clean(self): cleaned_data = super(PasswordConfirmForm, self).clean() password = self.cleaned_data.get('password') password_confirm = self.cleaned_data.get('password_confirm') if password != password_confirm: raise ValidationError(u'password is not match.') return cleaned_data
cleanメソッドでraiseされたValidationErrorはフィールドに紐付けられず、NON_FIELD_ERRORとして扱われる
>>> from accounts.forms import PasswordConfirmForm
>>> f = PasswordConfirmForm(dict(password='abc', password_confirm='xyz'))
>>> f.is_valid()
False
>>> f.errors
{u'__all__': [u'password is not match.']}
>>> f.non_field_errors()
[u'password is not match.']
cleanメソッドでエラーをフィールドに紐付けたい場合がある。
今まではこんな感じでやっていた。
# coding=utf-8 from django import forms from django.forms.util import ErrorList class PasswordConfirmForm(forms.Form): password = forms.CharField() password_confirm = forms.CharField() def clean(self): cleaned_data = super(PasswordConfirmForm, self).clean() password = self.cleaned_data.get('password') password_confirm = self.cleaned_data.get('password_confirm') if password != password_confirm: errors = self._errors.setdefault("password_confirm", ErrorList()) errors.append(u'password is not match.') return cleaned_data
>>> from accounts.forms import PasswordConfirmForm
>>> f = PasswordConfirmForm(dict(password='abc', password_confirm='xyz'))
>>> f.is_valid()
False
>>> f.errors
{'password_confirm': [u'password is not match.']}
>>> f.non_field_errors()
[]
>>> f['password_confirm'].errors
[u'password is not match.']
Django 1.7a2だとForm.add_errorというメソッドが用意されてるので、面倒なことしなくてもよくなる。The Forms API ― Django 1.7a2 documentation
サンプルはエラー文字列を渡しているけど、ValidationErrorのインスタンスを渡すのが推奨されているらしい。
# coding=utf-8 from django import forms class PasswordConfirmForm(forms.Form): password = forms.CharField() password_confirm = forms.CharField() def clean(self): cleaned_data = super(PasswordConfirmForm, self).clean() password = self.cleaned_data.get('password') password_confirm = self.cleaned_data.get('password_confirm') if password != password_confirm: self.add_error('password_confirm', 'password is not match.') return cleaned_data>>> from accounts.forms import PasswordConfirmForm
>>> f = PasswordConfirmForm(dict(password='abc', password_confirm='xyz'))
>>> f.is_valid()
False
>>> f.errors
{'password_confirm': [u'password is not match.']}