在前面的例子里面 http://beanxyz.blog.51cto.com/5570417/1963702,已经演示了form可以自动地对正则进行合法的判断,如果不合法,会直接显示错误信息。


但是这个功能并不完善,比如说一个数据可能正则判断合法了,但是不符合唯一性的判断,那么怎么处理?我们可以通过 form的 hook(钩子)进行自定义。


如果我们查看 Is_valid这个方法,我们可以看见

    def is_valid(self):
        """
        Returns True if the form has no errors. Otherwise, False. If errors are
        being ignored, returns False.
        """
        return self.is_bound and not self.errors


追踪self.errors

    @property
    def errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors


追踪 full_clean(), 这里是系统给我们预留的3个hook,分别代表对字段的clean,对整个form的clean,和clean之后的操作

    def full_clean(self):
        """
        Cleans all of self.data and populates self._errors and
        self.cleaned_data.
        """
        self._errors = ErrorDict()
        if not self.is_bound:  # Stop further processing.
            return
        self.cleaned_data = {}
        # If the form is permitted to be empty, and none of the form data has
        # changed from the initial data, short circuit any validation.
        if self.empty_permitted and not self.has_changed():
            return
        self._clean_fields()
        self._clean_form()
        self._post_clean()


因此form验证的顺序是,默认的正则判断-》对应每一个字段单独的验证(clean)-》整个form的clean验证-》clean之后的操作


实例:


from django.core.exceptions import ValidationError
from django import forms
from django.forms import widgets
from django.forms import fields
from app01 import models
class RegisterForm(forms.Form):
    user = fields.CharField
    email = fields.EmailField
    def clean_user(self):  # 对user做一个单独的验证
        c = models.UserType.objects.filter(name=self.cleaned_data['user'])
        if c :  # 如果用户名已经存在,提示报错信息
            raise ValidationError('用户名已经存在',code='xxx')
        else:  # 不存在,验证通过
            return self.cleaned_data['user']
    def clean_email(self):  # 对email做单独的验证
        # 验证必须要有返回值
        return self.cleaned_data['email']
# 验证顺序:
    # 先user字段,在clean_user方法
    # 再email字段,在clean_email方法
    
 def register(request):
    from cmdb.forms import RegisterForm    from django.core.exceptions import NON_FIELD_ERRORS
    obj = RegisterForm(request.POST)    if obj.is_valid():
        obj.cleand_data    else:
        obj.errors
        {            
            'user':[{'code':'required','message':'xxxx'}],            
            'pwd':[{'code':'required','message':'xxxx'}],            
            # 上面每个字段的错误信息放在里面,那clean总的错误信息放在哪里?
            '__all__':[],  # 特殊的整体错误信息,放在这里
            # NON_FIELD_ERRORS:[], 和 __all__ 一个意思。
        }