概述
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_<field>&()的最后必须返回验证完毕或修改后的值.
form验证中自定义验证机制
需求
- 用户输入的是否为cc,如果是,提示用户
- 验证二次输入的密码是否匹配,如果不一致,提示用户
看下views.py中的代码:
1 from django import forms 2 from django.core.exceptions import ValidationError 3 import re 4 5 6 def mobile_validate(value): 7 mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') 8 if not mobile_re.match(value): 9 raise ValidationError('手机号码格式错误') 10 11 12 class LoginForm(forms.Form): 13 user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'}) 14 pwd = forms.CharField(required=True, 15 min_length=6, 16 max_length=10, 17 error_messages={'required': '密码不能为空.', 'min_length': "至少6位"}) 18 19 pwd2 = forms.CharField(required=True, 20 min_length=6, 21 max_length=10, 22 error_messages={'required': '密码不能为空.', 'min_length': "至少6位"}) 23 24 25 num = forms.IntegerField(error_messages={'required': '数字不能空.', 'invalid': '必须输入数字'}) 26 27 phone = forms.CharField(validators=[mobile_validate, ], ) 28 29 def clean_user(self): 30 user = self.cleaned_data.get('user') 31 if user == 'cc': 32 raise forms.ValidationError('用户名是我的!') 33 34 return user 35 36 def clean(self): 37 cleaned_data = self.cleaned_data 38 pwd = cleaned_data['pwd'] 39 40 pwd2 = cleaned_data['pwd2'] 41 print(pwd,pwd2) 42 if pwd != pwd2: 43 raise forms.ValidationError('二次输入密码不匹配') 44 return cleaned_data #注意此处一定要return clean_data,否则会报错 45 46 47 def login(request): 48 if request.POST: 49 objPost = LoginForm(request.POST) 50 ret = objPost.is_valid() 51 if ret: 52 print(objPost.clean()) 53 else: 54 from django.forms.utils import ErrorDict 55 print(objPost.non_field_errors()) 56 57 pass 58 return render(request, 'login.html', {'obj1': objPost}) 59 else: 60 objGet = LoginForm() 61 return render(request, 'login.html', {'obj1': objGet})
HTML 页面中,如果想取clean()报错的信息,因其本身是一个迭代器,所以我们可以循环返回数据的 “non_field_errors
”取值,比如:
1 <div> 2 {% if obj1.non_field_errors %} 3 {% for item in obj1.non_field_errors %} 4 <span class="error_msg">{{ item }}</span> 5 {% endfor %} 6 {% endif %}
来看下html中的设置:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 .error_msg{ 8 color: red; 9 } 10 </style> 11 </head> 12 <body> 13 <form action="/login/" method="POST"> 14 <div>用户名: 15 {{ obj1.user }} 16 {% if obj1.errors.user %} 17 <span class="error_msg">{{ obj1.errors.user.0 }}</span> 18 {% endif %} 19 </div> 20 <div>密码: 21 {{ obj1.pwd }} 22 {% if obj1.errors.pwd %} 23 <span class="error_msg">{{ obj1.errors.pwd.0 }}</span> 24 {% endif %} 25 </div> 26 <div>确认密码: 27 {{ obj1.pwd2 }} 28 {% if obj1.errors.pwd2 %} 29 <span class="error_msg">{{ obj1.errors.pwd2.0 }}</span> 30 {% endif %} 31 </div> 32 <div>数字: 33 {{ obj1.num }} 34 {% if obj1.errors.num %} 35 <span class="error_msg">{{ obj1.errors.num.0 }}</span> 36 {% endif %} 37 </div> 38 <div>电话: 39 {{ obj1.phone }} 40 {% if obj1.errors.phone %} 41 <span class="error_msg">{{ obj1.errors.phone.0 }}</span> 42 {% endif %} 43 </div> 44 <div> 45 {% if obj1.non_field_errors %} 46 {% for item in obj1.non_field_errors %} 47 <span class="error_msg">{{ item }}</span> 48 {% endfor %} 49 {% endif %} 50 </div> 51 <input type="submit" value="提交"/> 52 53 </form> 54 55 56 </body> 57 </html>