Django之form表单验证

概述

django框架提供了一个forms类,来处理web开发中的表单相关事项。众所周知,form最常做的是对用户输入的内容进行验证,为此django的forms类提供了全面的内容验证支持。

验证流程

  1. 函数full_clean()依次调用每个field的clean()函数,该函数针对field的max_length,unique等约束进行验证,如果验证成功则返回值,否则抛出ValidationError错误。如果有值返回,则放入form的cleaned_data字典中。
  2. 如果每个field的内置clean()函数没有抛出ValidationError错误,则调用以clean_开头,以field名字结尾的自定义field验证函数。验证成功和失败的处理方式同步骤1。
  3. 最后,调用form的clean()函数——注意,这里是form的clean(),而不是field的clean()——如果clean没有错误,那么它将返回cleaned_data字典。
  4. 如果到这一步没有ValidationError抛出,那么cleaned_data字典就填满了有效数据。否则cleaned_data不存在,form的另外一个字典errors填上验证错误。在template中,每个field获取自己错误的方式是:{{ form.username.errors }}。
  5. 最后,如果有错误is_valid()返回False,否则返回True。

  注意一点:自定义验证机制时:clean()和clean_<field>&()的最后必须返回验证完毕或修改后的值.

form验证中自定义验证机制

需求

  1. 用户输入的是否为cc,如果是,提示用户
  2. 验证二次输入的密码是否匹配,如果不一致,提示用户

看下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>

猜你喜欢

转载自www.cnblogs.com/songtao1600/p/9020770.html