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
