form表单最大的作用就是验证功能了,通过cleaned_data清洗,我们可以获取传来的值,通过参数、验证器、自定义验证方法,我们可以做到很多的验证。
验证器可用于在不同类型的字段之间重用验证逻辑。validators有自带的验证器,也可以自己定义一个验证器。在验证某个字段的时候,可以传递一个validators参数用来指定验证器,进一步对数据进行过滤。验证器有很多,但是很多验证器其实已经通过这个Field或者一些参数就可以指定了。比如EmailValidator,可以通过EmailField来指定,比如MaxValueValidator,可以通过max_value参数来指定。以下是一些常用的验证器:
from django.core import validators
MaxValueValidator
:验证最大值。MinValueValidator
:验证最小值。MinLengthValidator
:验证最小长度。MaxLengthValidator
:验证最大长度。EmailValidator
:验证是否是邮箱格式。URLValidator
:验证是否是URL
格式。RegexValidator
:如果还需要更加复杂的验证,那么可以通过正则表达式的验证器
其中最常用到的就是RegexValidator,他可以通过正则自己定义验证器。如下面自己定义的一个验证手机号的例子。自定义验证器后,将验证器加入到validators的列表中。
# 创建手机号的正则校验器mobile_validator = RegexValidator(r"^1[3-9]\d{9}$", "手机号码格式不正确")
mobile = forms.CharField(max_length=11, min_length=11, validators=[mobile_validator, ], error_messages={"min_length": "手机号长度有误", "max_length": "手机号长度有误", "required": "手机号不能为空"})
自定义验证
对于一些字段,可能还有一些更复杂的验证,我们可以采用函数的形式,构造自定义验证。一种是针对一个字段的验证,函数名为clean_字段名(self),还有一种是针对多个字段一起验证,函数名为clean(self),clean方法的第一步需要重新调用父类的clean方法。这两种方式,如果验证失败,那么就抛出一个验证错误ValidationError
。
# 验证手机号 if (not real_image_code) or (image_text != real_image_code): raise forms.ValidationError("图片验证失败")
from django import formsclass ContactForm(forms.Form): # Everything as before. ... def clean_recipients(self): data = self.cleaned_data['recipients'] if "fred@example.com" not in data: raise forms.ValidationError("You have forgotten about Fred!") # Always return a value to use as the new cleaned data, even if # this method didn't change it. return data
from django import formsclass RegisterTable(forms.Form): username = forms.CharField(min_length=1,max_length=10) phone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}", message="请输入正确的手机号码")]) # message会在表单类.errors.get_json_data()中获得 # 对某个字段进行自定义的验证方式是,定义一个方法,这个方法的名字定义规则是:clean_fieldname def clean_phone(self): phone = self.cleaned_data.get("phone") # 获得字段数据 ret = User.objects.filter(phone=phone).exists() # 如果已存在 if ret: raise forms.ValidationError(message="{}已经被注册".format(phone)) # 抛出异常 # message会在表单类.errors.get_json_data()中获得 else: return phone
下面是clean方法:
class RegisterTable(forms.Form): username = forms.CharField(min_length=1,max_length=10) phone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}", message="请输入正确的手机号码")]) pwd = forms.CharField(min_length=5) #密码 pwd_repeat = forms.CharField(min_length=5) #重复的密码 def clean_phone(self): phone = self.cleaned_data.get("phone") ret = User.objects.filter(phone=phone).exists() if ret: raise forms.ValidationError(message="{}已经被注册".format(phone)) return phone def clean(self): #最后审查 ret = super(RegisterTable, self).clean() pwd = ret.get("pwd") # ==self.cleaned_data.get("pwd") pwd_repeat = ret.get("pwd_repeat") if pwd != pwd_repeat: raise forms.ValidationError(message="密码不一致") else: return ret