Py006-02-03forms表单验证

forms组件

校验字段

针对一个实例:注册用户讲解。

  • 前置准备

创建项目,创建一个orm表,一个注册页面

模型:models.py

1
2
3
4
5
6
7
8
9
10
11
12
class UserInfo(models.Model):
name=models.CharField(max_length=32)
pwd=models.CharField(max_length=32)
email=models.EmailField()
tel=models.CharField(max_length=32)

'''
# 别忘了settings.py里 注册 应用如 app01
# 数据库迁徙
python3 manage.py makemigrations
python3 manage.py migrate
'''

注册路由配置

1
2
3
4
5
6
from app01 import views

urlpatterns = [
path('admin/', admin.site.urls),
path('reg/',views.reg) # 注册页
]

reg.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<form action="" method="post">
{% csrf_token %}
<div>
<label for="user">用户名</label>
<p><input type="text" name="name" id="name"></p>
</div>
<div>
<label for="pwd">密码</label>
<p><input type="password" name="pwd" id="pwd"></p>
</div>
<div>
<label for="r_pwd">确认密码</label>
<p><input type="password" name="r_pwd" id="r_pwd"></p>
</div>
<div>
<label for="email">邮箱</label>
<p><input type="text" name="email" id="email"></p>
</div>
<div>
<label for="tel">手机号</label>
<p><input type="text" name="tel" id="tel"></p>
</div>
<input type="submit">
</form>

views.py

1
2
3
4
5
6
7
def reg(request):
if request.method=='POST':

print(request.POST)
return HttpResponse('ok')

return render(request,'reg.html')
  • 至此,准备工作完毕,
1
2
3
# 依次填写表单1,2,3,4,5。
# 打印如下信息
<QueryDict: {'csrfmiddlewaretoken': ['dTj3JNHHoZKrLZEXAJsoty9UxZ8vCJ3zqZH3gvIor4Lp1bKp8GFfmYS1Q4A58fji'], 'name': ['1'], 'pwd': ['2'], 'r_pwd': ['3'], 'email': ['4'],'tel':['5']}>

forms简单使用

  • 引入forms
  • 定义一个校验类如UserForm继承forms.Form
  • 自定义校验规则name = forms.CharField(min_length=4)
  • 根据校验字段生成UserForm初始化对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 引入forms
from django import forms

# 自定义表单校验
class UserForm(forms.Form):
# 定义校验字段的规则
name = forms.CharField(min_length=4) # 最少四个字符
email = forms.EmailField() # 邮箱校验


def reg(request):
if request.method=='POST':

form = UserForm({"name":'abcd','email':'123'})
# 所有值校验字段通过返回 true 10个字段其中一个失败返回false
print(form.is_valid()) # 返回布尔值 返回False email没有通过校验

return HttpResponse('ok')

return render(request,'reg.html')

'''
form = UserForm({"name":'abcd','email':'123@qq.com'})
form.is_valid() # True
'''

错写校验字段会如何?

1
2
3
4
5
form = UserForm({"names":'abcd','email':'123@qq.com'})
# 定义的UserForm里 为name 你传递names 显然不匹配
form.is_valid() # False

# 校验字段必须和定义里的字段相同

多出校验字段会咋样?

多了无所谓,只要定义的字段全匹配就ok

1
2
3
form = UserForm({"name":'abcd','email':'123@qq.com','age':22})
# 定义的UserForm里 为name,email 你多传递的key会被忽略
form.is_valid() # True

form.cleaned_data

这里是校验合法字段的字典

1
2
3
4
5
6
7
8
9
10
11
# 部分校验通过
form = UserForm({"names":'abcd','email':'123@qq.com','age':111})
print(form.cleaned_data)
# {'email': '123@qq.com'}


# -------------------
# 全部校验通过
form = UserForm({"name":'abcd','email':'123@qq.com','age':111})
print(form.cleaned_data)
# {'name': 'abcd', 'email': '123@qq.com'}

form.errors

校验失败字段对应的错误信息

1
2
3
form = UserForm({"name":'abc','email':'123@qq.com','age':111})
print(form.errors)
# <ul class="errorlist"><li>name<ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul></li></ul>

别看返回的是个ul实际是个字典类型

重写我们的UserForm对应实际的表单

1
2
3
4
5
6
7
class UserForm(forms.Form):
# 定义校验字段的规则
name = forms.CharField(min_length=4) # 最少四个字符
pwd = forms.CharField(min_length=4) # 最少四个字符
r_pwd = forms.CharField(min_length=4) # 最少四个字符
email = forms.EmailField() # 邮箱校验
tel = forms.CharField()

重写views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def reg(request):
if request.method=='POST':
# 表单会携带csrf_token字段 但是未在UserForm里定义所以会忽略
form = UserForm(request.POST)
if form.is_valid():
print(form.cleaned_data)
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict 字典
print(form.errors.get('name')) # ErrorList 列表
print(form.errors.get('name')[0]) # 具体的错误信息
return HttpResponse('ok')

return render(request,'reg.html')

# reg页面表单什么都不填写直接提交
'''
{}
<ul class="errorlist"><li>name<ul class="errorlist"><li>This field is required.</li></ul></li><li>pwd<ul class="errorlist"><li>This field is required.</li></ul></li><li>r_pwd<ul class="errorlist"><li>This field is required.</li></ul></li><li>email<ul class="errorlist"><li>This field is required.</li></ul></li><li>tel<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
<ul class="errorlist"><li>This field is required.</li></ul>
This field is required.
'''

forms渲染标签方式一

修改views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from django.shortcuts import render,HttpResponse

from django import forms

# 自定义表单校验
class UserForm(forms.Form):
# 定义校验字段的规则
name = forms.CharField(min_length=4) # 最少四个字符
pwd = forms.CharField(min_length=4) # 最少四个字符
r_pwd = forms.CharField(min_length=4) # 最少四个字符
email = forms.EmailField() # 邮箱校验
tel = forms.CharField()

def reg(request):
if request.method=='POST':

form = UserForm(request.POST)
if form.is_valid():
print(form.cleaned_data)
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict
print(form.errors.get('name')) # ErrorList
print(form.errors.get('name')[0]) # 具体的错误信息
return HttpResponse('ok')

# get请求的时候
form = UserForm()

return render(request,'reg.html',locals())

不传递参数初始化表单校验对象form = UserForm() 传递到模版里就以定义的字段可以生成表单标签

reg.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<form action="" method="post">
{% csrf_token %}
<div>
<label for="">用户名</label>
{{ form.name }}
</div>
<div>
<label for="">密码</label>
{{ form.pwd }}
</div>
<div>
<label for="">确认密码</label>
{{ form.r_pwd }}
</div>
<div>
<label for=""> 邮箱</label>
{{ form.email }}
</div>
<div>
<label for=""> 手机</label>
{{ form.tel }}
</div>

<input type="submit" class="btn btn-default pull-right">
</form>

forms渲染方式二

1
2
3
4
5
6
7
8
9
10
11
12
13
<form action="" method="post">
{% csrf_token %}

{% for field in form %}
<div>
<label for="">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<input type="submit">
</form>

# 这样渲染的label名是首字母大写的字段

我就要显示中文

设置label值

1
2
3
4
5
6
7
class UserForm(forms.Form):
# 定义校验字段的规则
name = forms.CharField(min_length=4,label='用户名') # 最少四个字符
pwd = forms.CharField(min_length=4,label='密码') # 最少四个字符
r_pwd = forms.CharField(min_length=4,label='密码') # 最少四个字符
email = forms.EmailField(label='邮箱') # 邮箱校验
tel = forms.CharField(label='电话')

forms渲染方式三

不建议使用,因为dom结构是定义死的。不够灵活

1
2
3
4
5
6
<form action="" method="post">
{% csrf_token %}

{{ form.as_p }}
<input type="submit">
</form>

forms渲染错误信息

在校验失败的地方 返回 HttpResponse(request,’reg.html’,locals())

为啥?

  • 你已经填写了表单,不管校验成功还是失败
  • 此时已经提交,页面会重刷,但是UserForm对象里有你传递的值,所以通过UserForm对象渲染标签的时候同时会把传递的值渲染到里面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def reg(request):

if request.method=='POST':
form = UserForm(request.POST)
if form.is_valid():
print(form.cleaned_data)
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict
print(form.errors.get('name')) # ErrorList
print(form.errors.get('name')[0]) # 具体的错误信息

return render(request,'reg.html',locals())

form = UserForm()

return render(request,'reg.html',locals())

错误信息form.字段.errors.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<form action="" method="post">
{% csrf_token %}
<div>
<label for="">用户名</label>
{{ form.name }} <span>{{ form.name.errors.0 }}</span>
</div>
<div>
<label for="">密码</label>
{{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span>
</div>
<div>
<label for="">确认密码</label>
{{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span>
</div>
<div>
<label for=""> 邮箱</label>
{{ form.email }} <span>{{ form.email.errors.0 }}</span>
</div>
<div>
<label for=""> 手机</label>
{{ form.tel }} <span>{{ form.tel.errors.0 }}</span>
</div>
<input type="submit" class="btn">
</form>

或者

1
2
3
4
5
6
7
8
9
10
11
<form action="" method="post" novalidate>
{% csrf_token %}

{% for field in form %}
<div>
<label for="">{{ field.label }}</label>
{{ field }} <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<input type="submit" class="btn btn-default">
</form>

forms参数配置

  • 错误信息定义为自己想要的
  • 渲染不同类型的表单select/password

渲染其他类型标签要引入widgets

定义错误信息要设置error_messages={“选项”:”错误信息”} required代表必填

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UserForm(forms.Form):
# 定义校验字段的规则
name = forms.CharField(min_length=4,label='用户名',error_messages={"required":'该字段不能为空'},
widgets = widgets.TextInput(attrs={"class":'form-control'}))
pwd = forms.CharField(min_length=4,label='密码',
widgets=widgets.PasswordInput())
r_pwd = forms.CharField(min_length=4,label='密码') # 最少四个字符
email = forms.EmailField(label='邮箱',error_messages={"required":'该字段不能为空',"invalid":"格式错误"}) # 邮箱校验
tel = forms.CharField(label='电话')

'''
widgets = widgets.TextInput(attrs={"class":'form-control'}))
给标签设置属性
'''