form——验证器Validators
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 forms
class 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 forms
class 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