概述
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}$\')
ifnot 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())
passreturn 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 %}<spanclass="error_msg">{{ item }}span>{% endfor %}{% endif %}
我来看下html中的设置:
<htmllang="en"><head><metacharset="UTF-8"><title>title><style>.error_msg{
color: red;
}
style>head><body><formaction="/login/"method="POST"><div>用户名:
{{ obj1.user }}{% if obj1.errors.user %}<spanclass="error_msg">{{ obj1.errors.user.0 }}span>{% endif %}div><div>密码:
{{ obj1.pwd }}{% if obj1.errors.pwd %}<spanclass="error_msg">{{ obj1.errors.pwd.0 }}span>{% endif %}div><div>确认密码:
{{ obj1.pwd2 }}{% if obj1.errors.pwd2 %}<spanclass="error_msg">{{ obj1.errors.pwd2.0 }}span>{% endif %}div><div>数字:
{{ obj1.num }}{% if obj1.errors.num %}<spanclass="error_msg">{{ obj1.errors.num.0 }}span>{% endif %}div><div>电话:
{{ obj1.phone }}{% if obj1.errors.phone %}<spanclass="error_msg">{{ obj1.errors.phone.0 }}span>{% endif %}div><div>{% if obj1.non_field_errors %}{% for item in obj1.non_field_errors %}<spanclass="error_msg">{{ item }}span>{% endfor %}{% endif %}div><inputtype="submit"value="提交"/>form>body>html>