WEB框架Django进阶----form验证

form组件

form验证

以前我们写form表单验证是这样的:

views.py

 1 def login(request):
 2     # f = open("templates/login.html","r",encoding="utf-8")
 3     # date = f.read()
 4     # f.close()
 5 
 6     error_msg = " "
 7     if request.method == "POST":
 8         user = request.POST.get("user",None)
 9         pwd = request.POST.get("pwd",None)
10 
11         if user=="root" and pwd=="123":
12             return redirect("http://www.baidu.com")
13         else:
14             error_msg = "用户名密码错误"
15 
16     return render(request,"login.html",{"error_msg":error_msg})
View Code

login.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <link rel="stylesheet" href="/static/commons.css" />
 7     <style>
 8         label{
 9             width: 80px;
10             text-align: right;
11             display: inline-block;
12         }
13     </style>
14 </head>
15 <body>
16         <form action="/login/" method="post">
17         <p>
18             <label for="username">用户名:</label>
19             <input id="username" name="user" type="text" />
20         </p>
21         <p>
22             <label for="password">密码:</label>
23             <input id="password" name="pwd" type="text" />
24             <input type="submit" value="提交" />
25             <span style="color: red">{{ error_msg }}</span>
26         </p>
27     </form>
28     <script src="/static/jquery-1.12.4.js"></script>
29 </body>
30 </html>
View Code

这样是可以的,但是不能细化每行的错误提示,其实在django中django自带了form的验证

是这样的

views.py

 1 from django import forms
 2 class FM(forms.Form):
 3     user = forms.CharField(error_messages={"required":"用户名不能为空"})
 4     pwd = forms.CharField(
 5         max_length=12,
 6         min_length=6,
 7         error_messages={"required":"密码不能为空","max_length":"密码长度不能超过12","min_length":"密码长度不能小于6"}
 8     )
 9     email = forms.EmailField(error_messages={"required":"邮箱不能为空","invalid":"邮箱格式不正确"})
10 
11 def fm(request):
12     if request.method == "GET":
13         return render(request,"fm.html")
14     elif request.method == "POST":
15         obj = FM(request.POST)
16         r1 = obj.is_valid()
17         # print(r1)
18         if r1:
19             print(obj.cleaned_data)
20         else:
21             print(obj.errors)
22             return render(request, "fm.html",{"obj":obj})

fm.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <form action="/fm/" method="post">
 9         {% csrf_token %}
10         <p><input type="text" name="user" />{{ obj.errors.user.0 }}</p>
11         <p><input type="text" name="pwd" />{{ obj.errors.pwd.0 }}</p>
12         <p><input type="text" name="email" />{{ obj.errors.email.0 }}</p>
13         <p><input type="submit" value="提交" /></p>
14 
15     </form>
16 </body>
17 </html>

显示效果:

但是还存在一个问题,你看,一点提交,数据都跑哪里了, 填写的数据不见了,怎么办呢?那要是我们想保留上一次操作的数据?

可以这样搞一下,

django中的form还可以生成<input>标签的

views.py

1 def fm(request):
2     if request.method == "GET":
3         obj = FM()
4         return render(request,"fm.html",{"obj":obj})

fm.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <form action="/fm/" method="post">
 9         {% csrf_token %}
10         <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>
11         <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
12         <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
13         <p><input type="submit" value="提交" /></p>
14 
15     </form>
16 </body>
17 </html>

显示效果:

 那如果提交是正确的数据呢?返回到后端显示的是一个字典格式的

那么这样写就可以在数据库中添加一个用户,完成注册了

 1 from app01 import models
 2 def fm(request):
 3     if request.method == "GET":
 4         obj = FM()
 5         return render(request,"fm.html",{"obj":obj})
 6     elif request.method == "POST":
 7         obj = FM(request.POST)
 8         r1 = obj.is_valid()
 9         # print(r1)
10         if r1:
11             #print(obj.cleaned_data)
12             models.UserInfo.objects.create(**obj.cleaned_data)   #完成注册添加进数据库

在html中还 可以在简化,看下面

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <form action="/fm/" method="post">
 9         {% csrf_token %}
10 {#        <p>{{ obj.user }}{{ obj.errors.user.0 }}</p>#}
11 {#        <p>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>#}
12 {#        <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>#}
13         {{ obj.as_p }}
14 
15         {{ obj.as_ul }}
16 
17         <table>{{ obj.as_table }}</table>
18         
19         <p><input type="submit" value="提交" /></p>
20 
21     </form>
22 </body>
23 </html>

显示效果:

但是不建议这样做,这样做不能针对每一个自定制的标签做处理。

form字段,用于对用户请求数据的验证

1 from django import forms
2 from django.forms import fields #字段
3 from django.forms import widgets #插件
4 class FM(forms.Form):
5     user = fields.CharField(
6         error_messages={"required":"用户名不能为空"},
7         widget=widgets.CheckboxInput(attrs={"class":"c1",})
8     )

 django的内置字段

  1 Field
  2     required=True,               是否允许为空
  3     widget=None,                 HTML插件
  4     label=None,                  用于生成Label标签或显示内容
  5     initial=None,                初始值
  6     help_text='',                帮助信息(在标签旁边显示)
  7     error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
  8     show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
  9     validators=[],               自定义验证规则
 10     localize=False,              是否支持本地化
 11     disabled=False,              是否可以编辑
 12     label_suffix=None            Label内容后缀
 13  
 14  
 15 CharField(Field)
 16     max_length=None,             最大长度
 17     min_length=None,             最小长度
 18     strip=True                   是否移除用户输入空白
 19  
 20 IntegerField(Field)
 21     max_value=None,              最大值
 22     min_value=None,              最小值
 23  
 24 FloatField(IntegerField)
 25     ...
 26  
 27 DecimalField(IntegerField)
 28     max_value=None,              最大值
 29     min_value=None,              最小值
 30     max_digits=None,             总长度
 31     decimal_places=None,         小数位长度
 32  
 33 BaseTemporalField(Field)
 34     input_formats=None          时间格式化   
 35  
 36 DateField(BaseTemporalField)    格式:2015-09-01
 37 TimeField(BaseTemporalField)    格式:11:12
 38 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 39  
 40 DurationField(Field)            时间间隔:%d %H:%M:%S.%f
 41     ...
 42  
 43 RegexField(CharField)
 44     regex,                      自定制正则表达式
 45     max_length=None,            最大长度
 46     min_length=None,            最小长度
 47     error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 48  
 49 EmailField(CharField)      
 50     ...
 51  
 52 FileField(Field)
 53     allow_empty_file=False     是否允许空文件
 54  
 55 ImageField(FileField)      
 56     ...
 57     注:需要PIL模块,pip3 install Pillow
 58     以上两个字典使用时,需要注意两点:
 59         - form表单中 enctype="multipart/form-data"
 60         - view函数中 obj = MyForm(request.POST, request.FILES)
 61  
 62 URLField(Field)
 63     ...
 64  
 65  
 66 BooleanField(Field)  
 67     ...
 68  
 69 NullBooleanField(BooleanField)
 70     ...
 71  
 72 ChoiceField(Field)
 73     ...
 74     choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
 75     required=True,             是否必填
 76     widget=None,               插件,默认select插件
 77     label=None,                Label内容
 78     initial=None,              初始值
 79     help_text='',              帮助提示
 80  
 81  
 82 ModelChoiceField(ChoiceField)
 83     ...                        django.forms.models.ModelChoiceField
 84     queryset,                  # 查询数据库中的数据
 85     empty_label="---------",   # 默认空显示内容
 86     to_field_name=None,        # HTML中value的值对应的字段
 87     limit_choices_to=None      # ModelForm中对queryset二次筛选
 88      
 89 ModelMultipleChoiceField(ModelChoiceField)
 90     ...                        django.forms.models.ModelMultipleChoiceField
 91  
 92  
 93      
 94 TypedChoiceField(ChoiceField)
 95     coerce = lambda val: val   对选中的值进行一次转换
 96     empty_value= ''            空值的默认值
 97  
 98 MultipleChoiceField(ChoiceField)
 99     ...
100  
101 TypedMultipleChoiceField(MultipleChoiceField)
102     coerce = lambda val: val   对选中的每一个值进行一次转换
103     empty_value= ''            空值的默认值
104  
105 ComboField(Field)
106     fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
107                                fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
108  
109 MultiValueField(Field)
110     PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
111  
112 SplitDateTimeField(MultiValueField)
113     input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
114     input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
115  
116 FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
117     path,                      文件夹路径
118     match=None,                正则匹配
119     recursive=False,           递归下面的文件夹
120     allow_files=True,          允许文件
121     allow_folders=False,       允许文件夹
122     required=True,
123     widget=None,
124     label=None,
125     initial=None,
126     help_text=''
127  
128 GenericIPAddressField
129     protocol='both',           both,ipv4,ipv6支持的IP格式
130     unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
131  
132 SlugField(CharField)           数字,字母,下划线,减号(连字符)
133     ...
134  
135 UUIDField(CharField)           uuid类型
136     ...
View Code

注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

 1 >>> import uuid
 2 
 3     # make a UUID based on the host ID and current time
 4     >>> uuid.uuid1()    # doctest: +SKIP
 5     UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
 6 
 7     # make a UUID using an MD5 hash of a namespace UUID and a name
 8     >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
 9     UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
10 
11     # make a random UUID
12     >>> uuid.uuid4()    # doctest: +SKIP
13     UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
14 
15     # make a UUID using a SHA-1 hash of a namespace UUID and a name
16     >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
17     UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
18 
19     # make a UUID from a string of hex digits (braces and hyphens ignored)
20     >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
21 
22     # convert a UUID to a string of hex digits in standard form
23     >>> str(x)
24     '00010203-0405-0607-0809-0a0b0c0d0e0f'
25 
26     # get the raw 16 bytes of the UUID
27     >>> x.bytes
28     b'x00x01x02x03x04x05x06x07x08	
x0bx0c
x0ex0f'
29 
30     # make a UUID from a 16-byte string
31     >>> uuid.UUID(bytes=x.bytes)
32     UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
View Code

form插件,用于生成HTML

 内置插件

 1 TextInput(Input)
 2 NumberInput(TextInput)
 3 EmailInput(TextInput)
 4 URLInput(TextInput)
 5 PasswordInput(TextInput)
 6 HiddenInput(TextInput)
 7 Textarea(Widget)
 8 DateInput(DateTimeBaseInput)
 9 DateTimeInput(DateTimeBaseInput)
10 TimeInput(DateTimeBaseInput)
11 CheckboxInput
12 Select
13 NullBooleanSelect
14 SelectMultiple
15 RadioSelect
16 CheckboxSelectMultiple
17 FileInput
18 ClearableFileInput
19 MultipleHiddenInput
20 SplitDateTimeWidget
21 SplitHiddenDateTimeWidget
22 SelectDateWidget
View Code

常用选择插件

 1 # 单radio,值为字符串
 2 # user = fields.CharField(
 3 #     initial=2,
 4 #     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
 5 # )
 6  
 7 # 单radio,值为字符串
 8 # user = fields.ChoiceField(
 9 #     choices=((1, '上海'), (2, '北京'),),
10 #     initial=2,
11 #     widget=widgets.RadioSelect
12 # )
13  
14 # 单select,值为字符串
15 # user = fields.CharField(
16 #     initial=2,
17 #     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
18 # )
19  
20 # 单select,值为字符串
21 # user = fields.ChoiceField(
22 #     choices=((1, '上海'), (2, '北京'),),
23 #     initial=2,
24 #     widget=widgets.Select
25 # )
26  
27 # 多选select,值为列表
28 # user = fields.MultipleChoiceField(
29 #     choices=((1,'上海'),(2,'北京'),),
30 #     initial=[1,],
31 #     widget=widgets.SelectMultiple
32 # )
33  
34  
35 # 单checkbox
36 # user = fields.CharField(
37 #     widget=widgets.CheckboxInput()
38 # )
39  
40  
41 # 多选checkbox,值为列表
42 # user = fields.MultipleChoiceField(
43 #     initial=[2, ],
44 #     choices=((1, '上海'), (2, '北京'),),
45 #     widget=widgets.CheckboxSelectMultiple
46 # )
View Code

初始化数据:

 1 from app01 import models
 2 def fm(request):
 3     if request.method == "GET":
 4         #从数据库中把数据拿到
 5         dic={
 6             "user":"uytr",
 7             "pwd":"123dfas",
 8             "email":"abcd@sina.com"
 9         }
10         obj = FM(initial=dic)
11         return render(request,"fm.html",{"obj":obj})

https://www.cnblogs.com/wupeiqi/articles/6144178.html

原文地址:https://www.cnblogs.com/garrett0220/p/9081764.html