文章目录

  • 一、form组件
  • 二、form表单的基本语法
    • 1. form表单类的书写
    • 2. 校验数据
    • 3. 渲染表单标签
  • 三、展示错误信息
    • 1. 展示错误信息
    • 2. 自定义错误信息
    • 3. 动态添加错误信息
  • 四、form表单的钩子函数(HOOK)
    • 1. 局部钩子(只涉及到一个字段)
    • 2. 全局钩子(涉及到多个字段)
  • 五、字段参数和类型
    • 1. 核心参数
      • `widget`参数
      • `validators`参数
      • 其他参数
    • 2. 常用类型

一、form组件

通常情况下,我们需要自己手动在HTML页面中,编写form标签和其内的其它元素。但这费时费力,而且容易出错,数据验证也比较麻烦。

因此,Django在内部集成了一个表单模块,专门用来帮助我们快速处理表单相关的内容。Django的表单模块给我们提供了下面三个主要功能:

  • 准备和重组数据,用于页面渲染;
  • 为数据创建HTML表单元素;
  • 接收和处理用户从客户端提交的表单及数据。

二、form表单的基本语法

编写Django的form表单,非常类似我们在模型系统里编写一个模型。在模型中,一个字段代表数据表的一列,而form表单中的一个字段代表<form>中的一个<input>元素。

1. form表单类的书写

在app文件夹下,新建一个forms.py文件写入:

from django import formsclass MyForm(forms.Form):# 最多不能超过20个字符,最少5个字符username = forms.CharField(max_length=20, min_length=5)password = forms.CharField(max_length=20, min_length=5)# 会验证输入是否符合邮箱格式email = forms.EmailField()

Form类中的每个字段不仅会验证数据,还会将数据转换为合适的格式。比如,DateField类型的字段会将收到的数据转换为python的datetime.data对象,无论我们传给它的是对象还是字符串,只要是有效的,它都会转换为datetime.data对象。

2. 校验数据

在终端中运行命令python manage.py shell,导入表单类,就可以在终端中进行以下步骤。

  • 创建表单对象:
    实例化表单类,参数为一个字典,键为类属性,值为需要提交的数据。

    form_obj1 = MyForm({'username':'mahugh','password':'123456','email':'123456'})  # email的值不符合邮箱格式form_obj2 = MyForm({'username':'mahugh','password':'123456','email':'123456@qq.com'})  # 所有值都符合条件
    
  • 查看验证是否通过:

    is_valid()方法,只要有一个键值对不符合验证条件,就返回false

    传入多余的键值对,不会影响验证结果,但少传键值对就会返回false

    form_obj1.is_valid()
    # 返回:Falseform_obj2.is_valid()
    # 返回:True
    
  • 查看通过验证的数据:

    cleaned_data只包含合法的(符合验证条件的)数据,多出的和不合法(不符合验证条件的)都不会被包含。

    form_obj1.cleaned_data
    # 返回:{'username': 'mahugh', 'password': '123456'}form_obj2.cleaned_data
    # 返回:{'username': 'mahugh', 'password': '123456', 'email': '123456@qq.com'}
    

    未调用is_valid()方法进行验证的form表单对象,调用cleaned_data属性查看正确的数据时,会报错'xxx' object has no attribute 'form_true'

  • 查看未通过验证的错误信息:

    errors只包含不合法数据的错误信息,多出的和合法的都不会被包含。

    form_obj1.errors
    # 返回:<ul class="errorlist"><li>email<ul class="errorlist"><li>输入一个有效的 Email 地址。</li></ul></li></ul>
    

    errors会被渲染成无序列表。

3. 渲染表单标签

视图中,生成一个表单对象,传递给模板:

def index(request):form_obj = MyForm(auto_id=True)return render(request, 'index.html', {'form_obj':form_obj})

如果 auto_id 设置为 True,那么表单输出将包括 <label> 标签,并将使用字段名作为每个表单字段的 id属性值,否则,不输出 <label> 标签,不设置id属性

在模板文件中,写入变量:

<form action="" method="post">{{ form_obj }}
</form>

这样就会将所有表单字段渲染为input框,并渲染label提示信息。提示信息默认为首字母大写的字段名称。但这种方法,过于死板,所以不常用。先看一些高级语法,之后总结常用写法。

高级语法:

  • 只渲染指定表单字段为input框,不渲染提示信息:

    {{ form_obj.username }}
    

    或者,使用循环渲染所有字段为input框:

    {% for obj in form_obj %}<!-- obj渲染出来只是一个个的input框 -->{{ obj }}
    {% endfor %}
    
  • 只渲染指定字段的提示信息,不渲染input框:

    {{ form_obj.username.label }}
    

    如果想自定义提示信息,可以在表单类中,传入label参数

    class MyForm(forms.Form):username = forms.CharField(max_length=20, min_length=5, label='姓名')
    

    这样,提示信息就会变成“姓名”了,而不是“Username”。

  • 使用指定的标签,包裹住字段被渲染后的html代码:

    <!-- 比如,以p标签包裹username字段 -->
    {{ form_obj.username.as_p }}
    

    最终渲染的html代码如下:

    <p><label for="id_username">姓名</label> <input type="text" name="username" maxlength="20" minlength="5" required="" id="id_username">
    </p>
    

    django支持的标签还有:

    <!-- 渲染为无序列表,以li标签进行包裹 -->
    {{ form_obj.as_ul }}<!-- 渲染为表格,必须放在table标签内 -->
    {{ form_obj.as_table }}
    

三、展示错误信息

测试准备:由于浏览器自带一些简单且容易跳过的验证措施,会干扰我们后端的测试验证,所以先在form标签中设置novalidate属性,来跳过浏览器验证

1. 展示错误信息

  • 首先在视图中使用is_valid()方法,验证后端提交的数据是否合法。合法就做后续步骤,不合法就将页面重新渲染一遍:

    def login_view(self, request):# request.POST可以看作是一个字典,因此可以直接用来实例化表单对象form_obj = MyForm(request.POS, auto_id=True)if form_obj.is_valid():return HttpResponse('好耶!验证通过了!')else:# 带着错误信息,再渲染一遍return render(request, 'index.html', context={'form_obj': form_obj})
    

    不要忘记auto_id=True参数!

  • 然后在模板的合适位置,写入错误信息变量:

    <form action="" method="post" novalidate>{% for form_obj in reg_form %}<label for="{{ form_obj.auto_id }}">{{ form_obj.label }}:</label>{{ form_obj }}{% if form_obj.errors %}{% for error in form_obj.errors %}<div>{{ error }}</div>{% endfor %}{% endif %}{% endfor %}
    

{{ form_obj.auto_id }}返回字段input框的id属性值,前提是实例化form表单对象时,写了auto_id=True参数。
因为{{ form_obj.errors }}默认是一个无序列表,使用for循环可以更好的展示多条错误信息
也可以写作{{ form_obj.errors.0 }},只获取错误信息的字符串,不显示 • 符号。

2. 自定义错误信息

在表单类的字段中,传入error_messages参数,该参数接收一个字典:

class MyForm(forms.Form):username = forms.CharField(max_length=20, min_length=5,error_messages={'max_length': '最多不能超过20个字符','min_length': '最少不能少于5个字符','required': '这个东西必须给我回答,不然揍你!'})# 邮箱比较特殊,需要单独记忆email = forms.EmailField(label='邮箱', error_messages={'invalid': '这™是邮箱?'})

字典当中的键称为“错误信息键”,值为验证失败时提示的错误信息。

required错误信息键,指在设置了required=True时(表示该字段必须填写),没有填写信息,就会提示该键后面的提示信息。

invalid则会在字段自带的验证未通过时,提示后面的信息,比如在上面的例子中,如果填写的不是一个邮箱,则会提示:“这™是邮箱?”。

不同的字段,拥有不同的错误信息键。常用的错误信息键会在字段 参数和类型 中讲到。

3. 动态添加错误信息

add_error()方法向表单特定字段添加错误信息。

form_obj.add_error('字段名', 错误信息)

字段的名称如果为None,error将作为Form.non_field_errors()的一个非字段错误。
错误信息可以是一个字符串,或者最好是 ValidationError 的实例,如:ValidationError("用户名已存在")
注意:Form.add_error()会自动从 cleaned_data 中删除相关字段

四、form表单的钩子函数(HOOK)

钩子函数是一类有特殊用法的函数,它会在特定节点自动触发完成响应操作。分为局部钩子函数和全局钩子函数两类。

1. 局部钩子(只涉及到一个字段)

局部钩子函数的函数名就是clean_字段名,你要给那个字段自定义规则,这个字段名就是谁!
比如:在django表单进行验证时,检查用户名是否含有违规字词(只涉及到username字段):

from django import forms
from django.core.exceptions import ValidationError
from app01.models import UserInfoclass MyForm(forms.Form):# 表单字段username = forms.CharField(label='用户名', max_length=12, min_length=2)# 局部钩子def clean_name(self):# 获取用户输入的用户名val = self.cleaned_data.get('username')# 查看数据库中是否有这个值ret = UserInfo.objects.filter(username=val) # 如果在数据库中没有,就通过匹配if not ret: return val# 否则,说明在数据库中有该用户名else:raise ValidationError("用户名已存在")

2. 全局钩子(涉及到多个字段)

全局钩子的函数名必须是clean()
比如:在django表单进行验证时,检查两次用户密码是否一致(涉及到password和confirm_password两个字段):

from django import forms
from django.core.exceptions import ValidationError
from app01.models import UserInfoclass MyForm(forms.Form):# 表单字段password = forms.CharField(label='密码', max_length=18, min_length=6)confirm_password = forms.CharField(label='确认密码', max_length=18, min_length=6)# 全局钩子def clean(self):pwd=self.cleaned_data.get("password")  r_pwd=self.cleaned_data.get("confirm_password")# 上面两个,有可能自带规则或自定义规则未通过,则get取值是空if pwd and r_pwd: # 如果两个都通过了第一层说明clean_data中有值就是trueif pwd==r_pwd:return self.cleaned_dataelse:raise ValidationError("两次密码不一致")else:  '''如果两个只要有其中一个不在clean_data里,那就没必要在比较了,因为本身就已经在errors里了'''return self.cleaned_data

五、字段参数和类型

1. 核心参数

  • label:用来自定义表单的提示信息(label标签的文本)。

  • error_messages:用于自定义验证不通过时的提示信息,在上面的自定义错误信息一节中已经讲过。

  • initial:用来给字段设置默认值,对应input标签的value属性。

  • required:指定该字段是否是必须填写的,默认值为true,表示该字段必须填写,否则不能通过验证。

widget参数

为字段指定一个Widget类,它有以下作用:

  • 指定部件,对应的是input的type属性:

    widget=forms.TextInput  # 普通文本类型
    widget=forms.PasswordInput  # 密码类型
    widget=forms.EmailInput  # 邮箱类型
    

    较为复杂的部件:

    • 单选按钮RadioSelect(对应radio):

      gender = forms.fields.ChoiceField(choices=((1, "男"), (2, "女"), (3, "保密")),label="性别",initial=3,widget=forms.RadioSelect()
      )
      
    • 选择框CheckboxInput(对应checkbox):

      # 单选框
      keep = forms.ChoiceField(label="是否记住密码",initial="checked",widget=forms.CheckboxInput()
      )# 多选框
      hobby = forms.MultipleChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),label="爱好",initial=[1, 3],widget=forms.CheckboxSelectMultiple()
      )
      
    • 下拉框CheckboxInput(对应option):

      # 单选下拉框
      hobby = forms.ChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),label="爱好",initial=3,widget=forms.Select()
      )# 多选下拉框
      hobby = forms.MultipleChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),label="爱好",initial=[1, 3],widget=forms.SelectMultiple()
      )
      

    更多内置部件参考官方文档:传送门

  • 传入参数,多用于设置标签的属性值:
    比如设置class属性,使用attrs参数:

    widget=forms.TextInput(attrs={'class': 'c1 c2 c3'}
    )
    

validators参数

给字段提供一个验证函数列表,用于自定义验证规则:

from django.core.exceptions import ValidationError# 这个东西是用来翻译东西的
from django.utils.translation import gettext_lazy as _def check_username(value):# 阿巴阿巴,验证操作……if 阿巴阿巴:# 验证不通过,抛出异常raise ValidationError(# 错误信息,翻译用不用看你自己_('%(value)这玩意得这个样子才行'),params={'value': value},)class MyForm():username = forms.CharField(validators=[check_username])

之后,username字段就会使用check_username函数进行验证。django还自带了一些验证器,比如RegexValidator验证器可以帮助我们通过正则表达式,快速书写验证方法:

validators=[# 参数为正则表达式和错误信息RegexValidator(r'我是正则表达式', '你这玩意不符合我这个正则表达式啊')]

更多内置验证器参考官方文档:传送门

其他参数

  • help_text='': 帮助信息(在标签旁边显示)
  • localize=False:是否支持本地化
  • disabled=False:是否可以编辑
  • label_suffix=None:Label内容后缀

2. 常用类型

  • BooleanField

    • 默认部件:CheckboxInput
    • 空值:False
    • 规范化为:Python 的 TrueFalse 值。
    • 如果字段有 required=True,则验证该值是否为 True (例如,复选框被选中)。
    • 错误信息键:required
  • CharField

    • 默认部件:TextInput

    • 空值:empty_value的值。

    • 规范化为:一个字符串。

    • 如果提供了 max_lengthmin_length,则验证输入的字符数。否则,所有输入都有效。

    • 错误信息键:requiredmax_lengthmin_length

    • 可选参数:

      max_length:最大字符数。

      min_length:最小字符数。

      strip:如果 True (默认),该值将被去掉前面和末尾的空白。

      empty_value:用来表示“空”的值。默认为空字符串。

  • IntegerField

    Field.localizeFalse 时是 NumberInput 否则,该字段的默认表单部件是 TextInput 否则,该字段的默认表单部件是 TextInput

    • 空值:None

    • 规范化为:Python 的整数。

    • 验证给定值是否为整数。

    • 错误信息键:requiredinvalidmax_valuemin_value

    • 可选参数:

      max_value:最大值。

      min_value:最小值。

  • DecimalField

    Field.localizeFalse 时是 NumberInput否则,该字段的默认表单部件是 TextInput

    • 空值:None

    • 规范化为:Python 的 decimal

    • 验证给定值是否为十进制。如果提供了 max_valuemin_value,则额外验证值的范围。前面和后面的空格会被忽略。

    • 错误信息键:requiredinvalidmax_valuemin_valuemax_digitsmax_decimal_placesmax_whole_digits

    • 可选的参数:

      max_value=None:最大值。
      min_value=None:最小值。

      max_digits:最大数字总位数。

      decimal_places:小数位数。

  • DateField

    • 默认部件:DateInput

    • 空值:None

    • 规范化为:Python 的 datetime.date 对象。

    • 验证给定值是 datetime.datedatetime.datetime 或以特定日期格式化的字符串。

    • 格式:“2015-09-01”

    • 错误信息键:requiredinvalid

    • 可选的参数:

      input_formats:用于将字符串转换为有效的 datetime.date 对象的格式列表,使用的是time模块的那一套格式化方法。

  • TimeField

    DateField基本相同,只有格式不同:“11:12”

  • DateTimeField

    DateField基本相同,只有格式不同:“2015-09-01 11:12”

  • EmailField

    • 默认部件:EmailInput

    • 空值:empty_value` 的值。

    • 规范化为:一个字符串。

    • 使用 EmailValidator来验证给定的值是一个有效的电子邮件地址,使用一个适度复杂的正则表达式。

    • 错误信息键:requiredinvalid:输入内容不符合邮箱格式时提示的错误信息。

    • 可选参数:

      max_lengthmin_lengthempty_value,它们的工作原理与 CharField 一样。

  • FileField

    • 默认部件:ClearableFileInput

    • 空值:None

    • 规范化为:一个 UploadedFile 对象,它将文件内容和文件名包装成一个单一对象。

    • 可以验证非空文件数据已经绑定到表单中。

    • 错误信息键:requiredinvalidmissingemptymax_length

    • 可选的验证参数:

      max_length :文件名的最大长度。

      allow_empty_file:是否允许文件内容为空。

    更多表单字段类型参考官方文档:传送门

django2.2-form表单详解相关推荐

  1. HTML第三章 form表单(详解,内含详细代码示例)

    目录 1.特点 2. 表单的语法和属性 3. input元素 4. select和下拉选择框 5. textarea多行文本域 6.label关联控件 每日一句 1.特点 提供了一些可视化的输入控件 ...

  2. Form 表单详解:案例、CSS 美化

    本文要点: 常见表单 表单的性质 表单CSS美化 使用 radio 实现 Tab 选项卡 什么是表单 用户通过表单填写信息,然后通过计算机网络传送给服务器.表单标签不是一个标签,而是一组标签,因为不同 ...

  3. js入门·表单详解一(修改表单属性,修改表单元素值)

    实在javascript入门·Document对象入门讲解(访问表单,创建新页,获取页标题) 一文中,我们已经把表单的一些基本访问等弄清楚了,下面我们深入的学下表单的属性以及对表单元素的简单操作! 演 ...

  4. form提交后台注解拿不到数据_Form表单详解

    主要内容Form表单.表单元素.表单元素的属性.HTML5新增type类型和HTML新增属性 知乎视频​www.zhihu.com 知乎视频​www.zhihu.com 知乎视频​www.zhihu. ...

  5. 菜鸟教程:HTML表单详解

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.表单元素form 二.form元素的属性 1.action 2.method 3.enctype 4.注意事项 三 ...

  6. layui单选框verify_layui lay-verify form表单自定义验证规则详解

    虽然layui的官方文档已经是写的比较详细,但是初次使用的时候总会懵一下,这里纪录一下lay-verify自定义验证规则的时候到底放哪. html: 提交 js: form.verify({ //数组 ...

  7. form表单提交三种方式,demo实例详解

    第一种:使用type=submit 可以直接提交 <html><head><title>submit直接提交</title></head>& ...

  8. 微信小程序form表单提交到MYSQL实例详解(PHP)

    1.小程序相对于之前的WEB+PHP建站来说,个人理解为只是将web放到了微信端,用小程序固定的格式前前端进行布局.事件触发和数据的输送和读取,服务器端可以用任何后端语言写,但是所有的数据都要以JSO ...

  9. django之Form表单

    HTML表单 在HTML中,表单是<form>...</form> 之间元素的集合,它们允许访问者输入文本.选择选项.操作对象和控制等等,然后将信息发送回服务器. 某些表单的元 ...

  10. html表单怎么设置编码,form 表单 设置编码和页面编码

    var isIE=!!window.ActiveXObject; if(isIE && document.charset!="utf-8")location.rel ...

最新文章

  1. mysql 绿色版远程访问_【Linux】MySQL解压版安装及允许远程访问
  2. java中bean文件主要实现内容_JavaBean简单及使用
  3. 指针的运用与strcpy函数的优化
  4. 一份字节跳动面试官给你的Java技术面试指南,彻底帮你搞懂
  5. UVa 11307 - Alternative Arborescence(dp)
  6. Leetcode 213. 打家劫舍 II (每日一题 20211009)
  7. YOLO学习-3:ubuntu16.04+ yolov3(darknet)+GPU(nvidia 1080ti)+opencv2.4.11 摄像头测试实践
  8. boost::stable_sort相关的测试程序
  9. Java多线程(十)之ReentrantReadWriteLock深入分析
  10. Js中Currying的应用
  11. 机器学习笔记2 – sklearn之iris数据集
  12. TYVJ P1073 加分二叉树 Label:区间dp
  13. 全球唯一标识符 System.Guid.NewGuid().ToString()
  14. 在线订餐系统php心得体会_基于php的网上订餐系统的设计与实现论文.doc
  15. docker 权限问题 Got permission denied while trying to connect to the Docker daemon socket at 。。。
  16. 复制移动VMware Workstation虚拟机文件产生的问题【转】
  17. php发送邮件功能(以QQ邮件为例)
  18. 一个IP账号,为啥通过路由器就可供多人同时使用?
  19. 命名实体识别的一点经验与技巧
  20. [SugerTangYL] 简易电子时钟Verilog设计

热门文章

  1. java 子类 继承父类的注解,spring使用注解通过子类注入父类的私有变量
  2. c语言实现16位定点数乘法,c语言 fixed-point 定点数 运算
  3. android播放器 重音,如何在SQLite查询中忽略重音(Android)
  4. android合入第三方库,Android中inflate和merge结合使用
  5. java模拟http_java模拟http请求的错误问题整理
  6. Windows下Nginx的启动、停止、重启等命令
  7. git合并分支,发布代码
  8. 声明,本博客文章均为转载,只为学习,不为其他用途。感谢技术大牛的技术分享,让我少走弯路。...
  9. Handler机制原理图、源码、使用!!!!!
  10. flask页面中Head标签内容为空问题