概述
django框架提供了一個forms類,來處理web開發中的表單相關事項。眾所周知,form最常做的是對用戶輸入的內容進行驗證,為此django的forms類提供了全面的內容驗證支持。
驗證過程

流程詳解
- 函數full_clean()依次調用每個field的clean()函數,該函數針對field的max_length,unique等約束進行驗證,如果驗證成功則返回值,否則拋出ValidationError錯誤。如果有值返回,則放入form的cleaned_data字典中。
- 如果每個field的內置clean()函數沒有拋出ValidationError錯誤,則調用以clean_開頭,以field名字結尾的自定義field驗證函數。驗證成功和失敗的處理方式同步驟1。
- 最后,調用form的clean()函數——注意,這里是form的clean(),而不是field的clean()——如果clean沒有錯誤,那么它將返回cleaned_data字典。
- 如果到這一步沒有ValidationError拋出,那么cleaned_data字典就填滿了有效數據。否則cleaned_data不存在,form的另外一個字典errors填上驗證錯誤。在template中,每個field獲取自己錯誤的方式是:{{ form.username.errors }}。
- 最后,如果有錯誤is_valid()返回False,否則返回True。
注意一點:自定義驗證機制時:clean()和clean_
form驗證中自定義驗證機制
需求
- 用戶輸入的是否為cc,如果是,提示用戶
- 驗證二次輸入的密碼是否匹配,如果不一致,提示用戶
看下views.py中的代碼:
...
from django import forms
from django.core.exceptions import ValidationError
import re
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手機號碼格式錯誤')
class LoginForm(forms.Form):
user = forms.CharField(required=True, error_messages={'required': '用戶名不能為空.'})
pwd = forms.CharField(required=True,
min_length=6,
max_length=10,
error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"})
pwd2 = forms.CharField(required=True,
min_length=6,
max_length=10,
error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"})
num = forms.IntegerField(error_messages={'required': '數字不能空.', 'invalid': '必須輸入數字'})
phone = forms.CharField(validators=[mobile_validate, ], )
def clean_user(self):
user = self.cleaned_data.get('user')
if user == 'cc':
raise forms.ValidationError('用戶名是我的!')
return user
def clean(self):
cleaned_data = self.cleaned_data
pwd = cleaned_data['pwd']
pwd2 = cleaned_data['pwd2']
print(pwd,pwd2)
if pwd != pwd2:
raise forms.ValidationError('二次輸入密碼不匹配')
return cleaned_data #注意此處一定要return clean_data,否則會報錯
def login(request):
if request.POST:
objPost = LoginForm(request.POST)
ret = objPost.is_valid()
if ret:
print(objPost.clean())
else:
from django.forms.utils import ErrorDict
print(objPost.non_field_errors())
pass
return render(request, 'login.html', {'obj1': objPost})
else:
objGet = LoginForm()
return render(request, 'login.html', {'obj1': objGet})
...
HTML 頁面中,如果想取clean()報錯的信息,因其本身是一個迭代器,所以我們可以循環返回數據的non_field_errors取值,比如:
<div>
{% if obj1.non_field_errors %}
{% for item in obj1.non_field_errors %}
<span class="error_msg">{{ item }}</span>
{% endfor %}
{% endif %}
我來看下html中的設置:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.error_msg{
color: red;
}
</style>
</head>
<body>
<form action="/login/" method="POST">
<div>用戶名:
{{ obj1.user }}
{% if obj1.errors.user %}
<span class="error_msg">{{ obj1.errors.user.0 }}</span>
{% endif %}
</div>
<div>密碼:
{{ obj1.pwd }}
{% if obj1.errors.pwd %}
<span class="error_msg">{{ obj1.errors.pwd.0 }}</span>
{% endif %}
</div>
<div>確認密碼:
{{ obj1.pwd2 }}
{% if obj1.errors.pwd2 %}
<span class="error_msg">{{ obj1.errors.pwd2.0 }}</span>
{% endif %}
</div>
<div>數字:
{{ obj1.num }}
{% if obj1.errors.num %}
<span class="error_msg">{{ obj1.errors.num.0 }}</span>
{% endif %}
</div>
<div>電話:
{{ obj1.phone }}
{% if obj1.errors.phone %}
<span class="error_msg">{{ obj1.errors.phone.0 }}</span>
{% endif %}
</div>
<div>
{% if obj1.non_field_errors %}
{% for item in obj1.non_field_errors %}
<span class="error_msg">{{ item }}</span>
{% endfor %}
{% endif %}
</div>
<input type="submit" value="提交"/>
</form>
</body>
</html>
