Django Form 组件
Django Form 组件用于对页面进行初始化,生成 HTML 标签,此外还可以对用户提交的数据进行校验(显示错误信息)。
报错信息显示顺序:
- 先显示字段属性中的错误信息,然后再显示局部钩子的错误信息。
- 若显示了字段属性的错误信息,就不会显示局部钩子的错误信息。
- 若有全局钩子,则全局钩子是等所有的数据都校验完,才开始进行校验,并且全局钩子的错误信息一定会显示。
使用 Form 组件,需要先导入 forms:
from django import forms
接下来我们在 app01 目录下创建一个 My_forms.py:
app01/My_forms.py
from
django
import
forms
from django. core . exceptions import ValidationError
from app01 import models
class EmpForm ( forms. Form ) :
name = forms. CharField ( min_length = 4 , label = "姓名" , error_messages = { "min_length" : "你太短了" , "required" : "该字段不能为空!" } )
age = forms. IntegerField ( label = "年龄" )
salary = forms. DecimalField ( label = "工资" )
from django. core . exceptions import ValidationError
from app01 import models
class EmpForm ( forms. Form ) :
name = forms. CharField ( min_length = 4 , label = "姓名" , error_messages = { "min_length" : "你太短了" , "required" : "该字段不能为空!" } )
age = forms. IntegerField ( label = "年龄" )
salary = forms. DecimalField ( label = "工资" )
字段属性:
- label :输入框前面的文本信息。
- error_message :自定义显示的错误信息,属性值是字典, 其中 required 为设置不能为空时显示的错误信息的 key。
app01/views.py
from
django.
shortcuts
import
render
,
HttpResponse
from app01. My_Forms import EmpForm
from app01 import models
from django. core . exceptions import ValidationError
# Create your views here.
def add_emp ( request ) :
if request. method == "GET" :
form = EmpForm ( )
return render ( request , "add_emp.html" , { "form" : form } )
else :
form = EmpForm ( request. POST )
if form. is_valid ( ) : # 进行数据校验
# 校验成功
data = form. cleaned_data # 校验成功的值,会放在cleaned_data里。
data. pop ( 'r_salary' )
print ( data )
models. Emp . objects . create ( **data )
return HttpResponse (
'ok'
)
# return render(request, "add_emp.html", {"form": form})
else :
print ( form. errors ) # 打印错误信息
clean_errors = form. errors . get ( "__all__" )
print ( 222 , clean_errors )
return render ( request , "add_emp.html" , { "form" : form , "clean_errors" : clean_errors } )
from app01. My_Forms import EmpForm
from app01 import models
from django. core . exceptions import ValidationError
# Create your views here.
def add_emp ( request ) :
if request. method == "GET" :
form = EmpForm ( )
return render ( request , "add_emp.html" , { "form" : form } )
else :
form = EmpForm ( request. POST )
if form. is_valid ( ) : # 进行数据校验
# 校验成功
data = form. cleaned_data # 校验成功的值,会放在cleaned_data里。
data. pop ( 'r_salary' )
print ( data )
models. Emp . objects . create ( **data )
return HttpResponse (
'ok'
)
# return render(request, "add_emp.html", {"form": form})
else :
print ( form. errors ) # 打印错误信息
clean_errors = form. errors . get ( "__all__" )
print ( 222 , clean_errors )
return render ( request , "add_emp.html" , { "form" : form , "clean_errors" : clean_errors } )
app01/urls.py 文件添加以下规则:
path('add_emp/', views.add_emp)
HTML 模版:
app01/add_emp.html
<
!
DOCTYPE
html
>
<
html
lang
=
"
en
"
>
<
head
>
<
meta
charset
=
"
UTF-8
"
>
<
title
>
</
title
>
</
head
>
<
body
>
<
h3
>
添加员工
</
h3
>
{#1、自己手动写HTML页面#}
<
form
action
=
"
"
method
=
"
post
"
>
<
p
>
姓名:
<
input
type
=
"
text
"
name
=
"
name
"
>
</
p
>
<
p
>
年龄:
<
input
type
=
"
text
"
name
=
"
age
"
>
</
p
>
<
p
>
工资:
<
input
type
=
"
text
"
name
=
"
salary
"
>
</
p
>
<
input
type
=
"
submit
"
>
</
form
>
{#2、通过form对象的as_p方法实现#}
{#
<
form
action
=
"
"
method
=
"
post
"
novalidate
>
#}
{# {% csrf_token %}#}
{# {{ form.as_p }}#}
{#
<
input
type
=
"
submit
"
>
#}
{#
</
form
>
#}
{#3、手动获取form对象的字段#}
{#
<
form
action
=
"
"
method
=
"
post
"
novalidate
>
#}
{# {% csrf_token %}#}
{#
<
div
>
#}
{#
<
label
for
=
"
id_{{ form.name.name }}
"
>
姓名
</
label
>
#}
{# {{ form.name }}
<
span
>
{{ form.name.errors.0 }}
</
span
>
#}
{#
</
div
>
#}
{#
<
div
>
#}
{#
<
label
for
=
"
id_{{ form.age.name }}
"
>
年龄
</
label
>
#}
{# {{ form.age }}
<
span
>
{{ form.age.errors.0 }}
</
span
>
#}
{#
</
div
>
#}
{#
<
div
>
#}
{#
<
label
for
=
"
id_salary
"
>
工资
</
label
>
#}
{# {{ form.salary }}
<
span
>
{{ form.salary.errors.0 }}
</
span
>
#}
{#
</
div
>
#}
{#
<
input
type
=
"
submit
"
>
#}
{#
</
form
>
#}
{#4、用for循环展示所有字段#}
{#
<
form
action
=
"
"
method
=
"
post
"
novalidate
>
#}
{# {% csrf_token %}#}
{# {% for field in form %}#}
{#
<
div
>
#}
{#
<
label
for
=
"
id_{{ field.name }}
"
>
{{ field.label }}
</
label
>
#}
{# {{ field }}
<
span
>
{{ field.errors.0 }}
</
span
>
#}
{#
</
div
>
#}
{# {% endfor %}#}
{#
<
input
type
=
"
submit
"
>
#}
{#
</
form
>
#}
</
body
>
</
html
>
运行结果如下图所示:
局部钩子和全局钩子
定义 Form 类:
app01/My_forms.py
from
django
import
forms
from django. core . exceptions import ValidationError
from app01 import models
class EmpForm ( forms. Form ) :
name = forms. CharField ( min_length = 5 , label = "姓名" , error_messages = { "required" : "该字段不能为空!" ,
"min_length" : "用户名太短。" } )
age = forms. IntegerField ( label = "年龄" )
salary = forms. DecimalField ( max_digits = 5 , decimal_places = 2 , label = "工资" )
r_salary = forms. DecimalField ( max_digits = 5 , decimal_places = 2 , label = "请再输入工资" )
def clean_name ( self ) : # 局部钩子
val = self . cleaned_data . get ( "name" )
if val. isdigit ( ) :
raise ValidationError ( "用户名不能是纯数字" )
elif models. Emp . objects . filter ( name = val ) :
raise ValidationError ( "用户名已存在!" )
else :
return val
def clean ( self ) : # 全局钩子 确认两次输入的工资是否一致。
val = self . cleaned_data . get ( "salary" )
r_val = self . cleaned_data . get ( "r_salary" )
if val == r_val:
return self . cleaned_data
else :
raise ValidationError ( "请确认工资是否一致。" )
from django. core . exceptions import ValidationError
from app01 import models
class EmpForm ( forms. Form ) :
name = forms. CharField ( min_length = 5 , label = "姓名" , error_messages = { "required" : "该字段不能为空!" ,
"min_length" : "用户名太短。" } )
age = forms. IntegerField ( label = "年龄" )
salary = forms. DecimalField ( max_digits = 5 , decimal_places = 2 , label = "工资" )
r_salary = forms. DecimalField ( max_digits = 5 , decimal_places = 2 , label = "请再输入工资" )
def clean_name ( self ) : # 局部钩子
val = self . cleaned_data . get ( "name" )
if val. isdigit ( ) :
raise ValidationError ( "用户名不能是纯数字" )
elif models. Emp . objects . filter ( name = val ) :
raise ValidationError ( "用户名已存在!" )
else :
return val
def clean ( self ) : # 全局钩子 确认两次输入的工资是否一致。
val = self . cleaned_data . get ( "salary" )
r_val = self . cleaned_data . get ( "r_salary" )
if val == r_val:
return self . cleaned_data
else :
raise ValidationError ( "请确认工资是否一致。" )
views.py 文件代码:
app01/views.py
def
add_emp
(
request
)
:
if request. method == "GET" :
form = EmpForm ( ) # 初始化form对象
return render ( request , "add_emp.html" , { "form" :form } )
else :
form = EmpForm ( request. POST ) # 将数据传给form对象
if form. is_valid ( ) : # 进行校验
data = form. cleaned_data
data. pop ( "r_salary" )
models. Emp . objects . create ( **data )
return redirect ( "/index/" )
else : # 校验失败
clear_errors = form. errors . get ( "__all__" ) # 获取全局钩子错误信息
return render ( request , "add_emp.html" , { "form" : form , "clear_errors" : clear_errors } )
if request. method == "GET" :
form = EmpForm ( ) # 初始化form对象
return render ( request , "add_emp.html" , { "form" :form } )
else :
form = EmpForm ( request. POST ) # 将数据传给form对象
if form. is_valid ( ) : # 进行校验
data = form. cleaned_data
data. pop ( "r_salary" )
models. Emp . objects . create ( **data )
return redirect ( "/index/" )
else : # 校验失败
clear_errors = form. errors . get ( "__all__" ) # 获取全局钩子错误信息
return render ( request , "add_emp.html" , { "form" : form , "clear_errors" : clear_errors } )
模板文件代码如下:
app01/add_emp.html
<
form
action
=
"
"
method
=
"
post
"
novalidate
>
{% csrf_token %}
<
div
>
<
label
for
=
"
id_{{ form.name.name }}
"
>
姓名
</
label
>
{{ form.name }}
<
span
>
{{ form.name.errors.0 }}
</
span
>
</
div
>
<
div
>
<
label
for
=
"
id_{{ form.age.name }}
"
>
年龄
</
label
>
{{ form.age }}
<
span
>
{{ form.age.errors.0 }}
</
span
>
</
div
>
<
div
>
<
label
for
=
"
id_salary
"
>
工资
</
label
>
{{ form.salary }}
<
span
>
{{ form.salary.errors.0 }}{{ clear_errors.0 }}
</
span
>
</
div
>
<
div
>
<
label
for
=
"
id_r_salary
"
>
请再输入工资
</
label
>
{{ form.r_salary }}
<
span
>
{{ form.r_salary.errors.0 }}{{ clear_errors.0 }}
</
span
>
</
div
>
<
input
type
=
"
submit
"
>
</
form
>
运行结果如下图所示: