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 = "工资" )

字段属性:

  • 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 } )

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 ( "请确认工资是否一致。" )

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 } )

模板文件代码如下:

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 >

运行结果如下图所示: