博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django Form组件
阅读量:5952 次
发布时间:2019-06-19

本文共 6984 字,大约阅读时间需要 23 分钟。

Form组件的简单使用

创建models类

以员工注册为例,创建一个表示员工表的类

models.py

from django.db import models# Create your models here.class Emp(models.Model):    name = models.CharField(max_length=32)    age = models.IntegerField()    salary = models.DecimalField(max_digits=8, decimal_places=2)

自定义Form类

在app1下面新建一个py文件

myForm.py(myForm是自己起的名字)

from django import formsclass EmpForm(forms.Form):    # 这里定义的字段和models里面的Emp表的字段必须一一对应    # label的值为input对应的label标签显示的内容    # error_message:验证未通过时显示的信息    name = forms.CharField(min_length=5, label='姓名', error_messages={        # 键:字段约束,required是form组件自动加的        # 值:验证未通过时显示的错误信息        'required': '姓名不能为空',        'min_length': '姓名至少为5位',    })  # 定制约束条件    age = forms.IntegerField(label='年龄')    salary = forms.DecimalField(max_digits=5, decimal_places=2, label='工资')

在视图函数里生成form对象并将form对象传给前端

views.py

from django.shortcuts import render, HttpResponse, redirectfrom app1.myForm import EmpFormfrom app1 import models# Create your views here.# 1. 自己写html页面# def login(request):#     if request.method == 'POST':#         pass#     else:#         return render(request, 'login.html')# 2. 用form自动生成html页面def login(request):    if request.method == 'POST':        # 把request.POST作为参数传进去        form = EmpForm(request.POST)        # 验证数据        if form.is_valid():            # 打印验证过的数据(可以写进数据库里)            print('form.cleaned_data:', form.cleaned_data)            models.Emp.objects.create(**form.cleaned_data)        else:            # 打印错误信息            print('form.errors:', form.errors)        return render(request, 'login.html', {'form': form})    else:        form = EmpForm()  # 实例化一个EmpForm对象        # 把form传给前端页面        return render(request, 'login.html', {'form': form})

在前端页面里用form对象生成html标签

login.html

    
Title

员工注册

{# 1. 自己写的html页面 #}{#
#}{# {% csrf_token %}#}{#

姓名:

#}{#

年龄:

#}{#

工资:

#}{#
#}{#
#}{# 2. aas_p: 一次展示所有字段 #}{#
#} {# Return this form rendered as HTML

s. #} {# 注意会把intfield渲染成type=number #}{# {

{ form.as_p }}#} {# 注意这里不会渲染submit标签,需要自己写 #}{# #}{##}{# 3. 手动获取form对象的字段 #}{#

#}{#
#} {# form.name是一个form表单下输入姓名的的标签 #} {# form.name.name是这个标签的值 #}{#
#} {# form组件会自动给input标签加上一个id,id名为id_字段名 #}{# {
{ form.name }}
{
{ form.name.errors.0 }}
#}{#
#}{#
#}{#
#}{# {
{ form.age }}
{
{ form.age.errors.0 }}
#}{#
#}{#
#}{#
#}{# {
{ form.salary }}
{
{ form.salary.errors.0 }}
#}{#
#}{#
#}{#
#}{# 4. for循环获取form对象的字段 #}
{% csrf_token %} {% for field in form %}
{# field.errors是一个列表,一般只显示第一个就可以了,解决了再显示下一个 #} {
{ field }}
{
{ field.errors.0 }}
{% endfor %}
{# 注意:用这种方式生成的input标签会自动加上required属性,也就是不能为空 #}{# 为空时提交不了,浏览器会显示必须填写此字段 #}{# 如果要去掉这个,在form里加上novalidate,告诉浏览器不用验证直接提交(正常期间狂不用加) #}{# 提交验证未通过时,form组件会保留用户输入的信息 #}

小结

什么是Form组件?

Form组件就是用一个类来表示form表单,类的属性对应form表单里面的input标签,注意不包括submit按钮

Form组件有哪些作用?

  • 页面初始化,生成HTML标签
  • 校验用户数据(显示错误信息)
  • HTML Form提交保留上次提交数据

局部钩子和全局钩子

局部钩子

什么是局部钩子?

在自定义Form类下面定义一个函数,名字叫:clean_字段名字,内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛出异常(ValidationError)

定义局部钩子

from django import formsfrom django.core.exceptions import ValidationErrorfrom app01 import modelsclass 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="工资")    # 注意这里函数的名字必须是clean_字段名的形式    def clean_name(self):  # 局部钩子        val = self.cleaned_data.get("name")        # 如果是数字        if val.isdigit():            # 抛出异常,使用ValidationError之前要导入            raise ValidationError("用户名不能是纯数字")        elif models.Emp.objects.filter(name=val):            raise ValidationError("用户名已存在!")        else:            return val

姓名输入纯数字时,显示错误信息
1542801-20190325193924696-1750874306.png

输入数据库已存在的姓名时,显示错误信息
1542801-20190325193831756-1465307449.png

输入正确的信息时,正常提交

1542801-20190325194158985-1458728546.png

检查数据库是否写入
1542801-20190325194313776-1767283979.png

全局钩子

什么是全局钩子?

局部钩子只是校验一个字段是否合法,如果要校验不同字段之间的值,需要使用全局钩子,也就是说,全局钩子是校验不同字段之间的一种方法

定义全局钩子

在EmpForm下面添加一个字段r_salary

class EmpForm(forms.Form):    # 这里定义的字段和models里面的Emp表的字段必须一一对应    # label的值为input对应的label标签显示的内容    # error_message:验证未通过时显示的信息    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="请再次输入工资")

定义clean方法

from django import formsfrom app1 import modelsfrom django.core.exceptions import ValidationErrorclass EmpForm(forms.Form):    # 这里定义的字段和models里面的Emp表的字段必须一一对应    # label的值为input对应的label标签显示的内容    # error_message:验证未通过时显示的信息    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):        salary = self.cleaned_data.get('salary')        r_salary = self.cleaned_data.get('r_salary')        if salary != r_salary:            raise ValidationError('工资输入有误')        else:            return self.cleaned_data

修改视图函数

from django.shortcuts import render, HttpResponse, redirectfrom app1.myForm import EmpFormfrom app1 import modelsdef login(request):    if request.method == 'POST':        # 把request.POST作为参数传进去        form = EmpForm(request.POST)        # 验证数据        if form.is_valid():            # 打印验证过的数据(可以写进数据库里)            data = form.cleaned_data            # 注意一定要删除多余的数据            data.pop('r_salary')            models.Emp.objects.create(**data)            return Httpresponse('添加成功')        else:            # 获取全局错误信息            clear_errors = form.errors.get('__all__')            return render(request, 'login.html', {'form': form, 'clear_errors': clear_errors})    else:        form = EmpForm()  # 实例化一个EmpForm对象        # 把form传给前端页面        return render(request, 'login.html', {'form': form})

两次工资输入不一致时
1542801-20190325203013010-1350064280.png

小结

  • 局部钩子和全局钩子都是用来校验用户输入的数据,校验成功返回对应的值,校验失败主动抛出异常
  • 局部钩子用来校验某个字段是否合法,着眼于局部;全局钩子用来校验多个字段之间是否满足某种关系(合法性),着眼于全局
  • 局部钩子在前,全局钩子在后

转载于:https://www.cnblogs.com/zzliu/p/10595140.html

你可能感兴趣的文章
Golang在Linux环境下的POSIX风格socket编程
查看>>
白话经典算法系列之中的一个 冒泡排序的三种实现
查看>>
Android四大组件之——Activity(一)定义、状态和后退栈(图文详解)
查看>>
详细解读Android中的搜索框(二)—— Search Dialog
查看>>
经常使用的webservice接口
查看>>
SAP ABAP第一,两,三代出口型BADI实现 解释的概念
查看>>
mybatis完美的实战教程
查看>>
What is the difference between DAO and DAL?
查看>>
java抓取动态生成的网页
查看>>
从零开始山寨Caffe·叁:全局线程管理器
查看>>
Ubuntu 修复windows启动项
查看>>
LCA在线算法ST算法
查看>>
PowerShell 导出SharePoint管理中心解决方式
查看>>
java操作mongodb(连接池)(转)
查看>>
Android入门(十一)SQLite CURD
查看>>
一个双线程下同一时候操作指针变量导致野指针出现的问题总结
查看>>
Servlet过滤器和监听器
查看>>
js闭包应用
查看>>
AndroidStudio
查看>>
10-10-归并排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版
查看>>