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_fieldnamedef 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 phonedef 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
?