在實際開發中,不僅僅是對輸入框字符的格式校驗,比如註冊功能,註冊帳號還得校驗資料庫是否已經有帳號被註冊過了。
有些場景不僅僅是對單個輸入框的字符校驗,比如修改密碼的時候,會涉及2個輸入框的數據格式校驗,像這些複雜的場景校驗需用到校驗鉤子來實現。
校驗form表單數據合法性,is_valid()方法調用順序:
1.欄位規則校驗,字符長度,是否必填等基本校驗
2.validators校驗(RegexValidator校驗器或自定義校驗函數)
3.局部鉤子(類中定義的以clean_欄位名命名的函數,校驗正常必須返回該欄位的值self.cleaned_data.get(『name』))
4.全局鉤子(類中定義的函數名clean,校驗正常必須返回該對象的校驗結果值return self.cleaned_data)
5.每一步通過校驗單結果都以字典形式保存在類對象的cleaned_data屬性中
ModelForm模型表單局部鉤子命名規則為clean欄位名稱,如:cleancity,clean_years。
super() 重寫`__init`,可以批量更新class屬性。
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class SubmitPageForm(forms.ModelForm):
class Meta:
model = Submit
# fields = "__all__" #全部欄位
fields = ["city", "years", "details"]
widgets = {
"city": widgets.TextInput(attrs={
"placeholder": "輸入城市:北京/上海/深圳"
}),
"years": widgets.TextInput(attrs={
"placeholder": "輸入年限"}),
"details": widgets.TextInput(attrs={
"placeholder": "輸入詳情"}),
}
labels = {
"city": "城 市",
"years": "年 限",
"details": "詳 情",
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 批量更新class屬性
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
def clean_city(self):
"""局部鉤子判斷城市必須是北京/上海/深圳其中一個"""
city_val = self.cleaned_data.get('city', '')
if city_val in ["北京", "上海", "深圳"]:
return city_val
else:
raise forms.ValidationError('城市只能選:北京/上海/深圳')
定義視圖
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class SubmitView(View):
def get(self, request):
form_obj = SubmitPageForm
return render(request, "submit.html", locals())
def post(self, request):
form_obj = SubmitPageForm(request.POST)
if form_obj.is_valid():
# data = form_obj.cleaned_data()
form_obj.save()
msg = "保存成功"
return HttpResponseRedirect('/total')
else:
# 全局鉤子自定義錯誤提示獲取
# print(form_obj.errors.get('__all__'))
# error_msg = form_obj.errors.get('__all__')
return render(request, "submit.html", locals())
模板內容如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>提交頁面</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div>
<form role="form" action="" method="POST" id="detail-form" >
{% csrf_token %}
{% for field in form_obj %}
<div>
{{ field.label_tag }}
{{ field }}
<div style="color: red"> {{ field.errors }} </div>
</div>
{% endfor %}
<p>
<input type="submit" value="提交" >
</p>
</form>
</div>
</body>
</html>
輸入不合法的內容,會顯示field.errors內容
針對單個欄位校驗可以用局部鉤子實現,如果我們要校驗多個欄位,比如校驗註冊的時候輸入2次密碼一致,可以用全局鉤子實現。
定義全局鉤子使用clean方法
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/
class SubmitPageForm(forms.ModelForm):
class Meta:
model = Salary
fields = "__all__" #全部欄位
# 省略中間代碼。。。。。# 全局鉤子
def clean(self):
"""在通過基礎驗證的乾淨數據中get獲取欄位"""
pwd1 = self.cleaned_data.get('password')
pwd2 = self.cleaned_data.get('password2')
if pwd1 and pwd2: # 這裡判斷2個欄位都是校驗通過
if pwd1 == pwd2:
# 數據沒問題,那麼原封不動返回即可
return self.cleaned_data
else:
# 錯誤信息儲存到 errors {'__all__':[e,]}
raise ValidationError('兩次密碼輸入不同')
else:
return self.cleaned_data
前端可以通過fomr_obj.errors.__all__獲取到內置校驗器的全部錯誤信息
2021年第八期《python接口web自動化+測試開發》7.17號開學(課程全面升級!) 加量不加價(新增postman, 贈送selenium和python基礎2個課)
本期上課時間:7月17號-10月16號,每周六、周日晚上20:30-22:30
聯繫微信/QQ:283340479