官方文档
在表单(无论是一般表单form.Form还是模型表单ModelForm),dir之后都会有一个属,为_errors的,他控制了表单验证是否成功。
比如,我们自己的表单xform(同样,无论xform是继承与一般表单还是模型表单,都一样)接受了request的post数据,有:
x=xform(request.POST)
下一步,我们验证表单,调用表单的is_validate方法,
有x.is_validate()
当表单验证错误,比如,用户注册的时候,username填入了已经存在的username,这个时候,则x.is_validate()=False。我们查看x.__dict__,有
'_errors': {'username': [u'User with this Username already exists.']},
一旦验证不通过,则我们就直接返回表单给模板,这个时候,我们就看到在username的input框中会有个错误提示,就是User with this Username already exists。
如果我们手动改变该属性,即x._errors={}或者x._errors=None,则会有
x.is_validate()=True
如果我们可以在模型之外添加我们对输入数据的额外的要求,比如,django中,User模型要求username唯一,但是,我想要求email也唯一,并且我们又不想改变django中的User模型(改变它,影响太大了,也懒得改源码了),则我们可以在自定义的xform中重写django.forms(无论是forms.Form,还是ModelForm)的clean方法。
对了clean方法,官方文档解释如下:
一般,验证表单的属性字段中,我们可以继承一个django的内置属性字段,如field(CharField),我们的属性field验证是有一下几个方法的:
1. 属性子类(field)的to_python方法,把得到的数据变成python类数据,转变不成功,就raise ValidationError
2. 属性子类(field)的 validate()方法,文档中说得貌似是指定验证的函数,这些验证函数成为验证者(validator),可以是多个,多个的话就是验证某个属性很多方面,像唯一性呀,一定要包含某些字符呀等等,验证不成功就raise ValidationError。
3. 属性子类(field)的 run_validators()方法,调用所有的验证者,收集错误,就是引发的ValidationError
4. 属性子类的clean方法的,它是上述三个方法按顺序调用的结果,并且捕获所有的ValidationError。如果没有raise ValidationError,表示验证通过,则返回cleaned_data。cleaned_data就表示数据验证通过了,干净了。
5. 表单中的clean_<fielddname>,。在表单form,无论是自定义的表单还是内置表单,这个就是4中的clean方法了。从名字就知道这是 在表单中再次验证某个属性的方法。你可以重写它。该方法不接受输入参数,你需要重表单中的cleaned_data中获取你要验证的数据。并且cleaned_data中的数据都是python类的数据,不是post进来的原生数据。
6. 表单的clean方法,他是一次验证多个属性,可以说是运行多个字段的clean方法,并且你可以重写它,添加额外的属性验证逻辑。下面我们用验证email是否唯一就是使用这一种方法。
所以,我们要添加额外的,针对User的email字段唯一,验证逻辑,我们可以使用第5个或者第6个方法。
第5个方法:
from django.contrib.auth.models import User from django.forms import ModelForm from django import forms class ReUserForm(ModelForm): def clean_email(self): cleaned_data=super(ReUserForm,self).clean() email_data=cleaned_data.get('email') if User.objects.filter(email=email_data).count() is not 0: raise forms.ValidationError(u'this email is already exist!') return cleaned_data class Meta: model=User fields=('username','email','password')
from django.contrib.auth.models import User from django.forms import ModelForm from django import forms class ReUserForm(ModelForm): class Meta: model=User fields=('username','email','password') def clean(self): cleaned_data=super(ReUserForm,self).clean() email_data=cleaned_data.get('email') if User.objects.filter(email=email_data).count() is not 0: msg = u'this email is already exists.' self._errors['email']=self.error_class([msg]) del cleaned_data['email'] return cleaned_data