目录
使用Form对象定义表单
Form对象的特性
表单字段的基类Field
常用的表单字段类型
基于Model定制的表单
ModelForm定义方式
表单中的常用方法
在Web站点中与后端服务进行交互,通常使用表单提交的方式。表单提交数据到达后端,首先要对数据做校验,对于不合法的数据需要拒绝并提示给前端,通过校验之后才能执行服务返回响应。由于所有的表单创建与处理流程都是相似的,所以,Django将这一过程抽象出来,形成表单系统。从在浏览器中显示表单到数据验证,再到对错误的处理,都可以由表单系统来完成。不仅如此,基于数据表(Model)创建表单也是很常见的情况,Django同样考虑到了这一点,并提供了ModelForm来简化功能实现。
表单系统的核心是Form对象,它将表单中的字段封装成一系列Field和验证规则,以此来自动地生成HTML表单标签。
与其他对象的定义规则类似,可以将Form对象定义在任何位置。但是,Django的建议是将它们定义在应用下的forms.py文件中。这样做的原因是归类存储,
from django import forms
class titleform(forms.Form):
title = forms.CharField(label='Topic title')
上面代码中,可以发现Form的定义与Model的定义非常相似,比较容易理解。这里的TopicSearchForm定义内容非常少。
- Django规定,所有的Form对象都必须继承自django.forms.Form,所以这里的TopicSearchForm符合条件。
- 定义了一个title属性,它是forms.CharField类型的Field,根据名称可以猜测此处将title指定为字符类型。label标签显式地指定了这个字段的名称,且Field有一个默认属性required为True,代表这个字段是必填的。
- 实现对所有字段的验证
- 每一个Form对象实例都会有一个is_valid方法,这个方法根据字段的定义验证实例的各个字段是否合法。如果所有的字段都是合法的,它会返回True,并且将数据存储到字典类型的cleaned_data属性中。
- 根据字段定义生成HTML
- 表单实例可以自动生成HTML表单元素,且默认输出使用HTML表格,但是并不提供<table>起始和结束标签。同时,也可以使用实例的as_ul方法获取列表形式的表单或使用as_p方法获取段落形式的表单。
- 由于表单实例可以直接返回HTML表单元素,所以,可以用它来替换模板文件中的字段定义。更方便的是,在没有正确填充表单时,它还可以返回错误信息的提示。
表单字段的基类Field
基类Field定义于django/forms/fields.py文件中,这里重点关注它的构造函数中定义的属性以及校验给定字段值是否有效的clean方法。
- required
- 设定当前的Field是否是必须提供的,默认值是True,即必须提供。
- widget
- 指定在页面中显示字段的控件,可以是Widget类或者Widget类实例。对于大多数情况,默认的控件使用TextInput。
- label
- 指定在页面中显示的字段的名称(标签)提示。如果不指定的话,则页面中将直接显示字段定义的变量名(首字母大写)。
- initial
- 指定字段的初始值,默认为None。当给字段的initial属性设定一个非空值时,页面中的对应表单将使用这个值填充。
- help_text
- 用于给当前的字段添加描述性信息,提示当前字段的作用或需要输入的内容解释。如果设定了该属性,则其在页面中将会显示在旁边。
- error_messages
- disabled
- 其默认值是False,如果修改为True,则当前的表单字段将不可编辑。当设置字段为不可编辑时,需要提供初始值(initial),否则,这个字段也就没有意义了。
常用的表单字段类型
Django表单系统内置了数十种表单字段类型,几乎可以满足所有的表单使用场景。如果这些内置的字段类型都不能满足所需的业务场景,Django也支持自定义Field类。
- CharField
- 其为字符串类型的表单字段,是最常见的表单字段类型,widget默认使用TextInput
- max_length限制字段值的最大长度
- min_length限制字段值的最小长度
- strip属性默认会执行Python字符串的strip方法,用于去除字符串开头和尾部的空格。如果不需要这样做,可以将strip属性设置为False:
- empty_value:用来表示"空"的值。默认为空字符串。
- IntegerField
- 其为整数类型的表单字段,widget默认使用NumberInput。
- 可选的max_value与min_value参数用于限定字段值的取值范围,且它们都是闭区间。如果提供了这两个参数(或其中之一),且给定的字段值不在取值范围内,将会抛出异常,并带有错误提示信息。
- BooleanField
- 其为布尔类型的表单字段,widget默认使用CheckboxInput。
- 由于基类Field的required属性默认是True,所以,在不做设置的情况下,BooleanField实例的required属性也是True。由于required为True要求这个字段值必须提供,所以,这种情况下,BooleanField类型的实例必须是True,否则将抛出异常,并提示:“This fieldis required.”。
- 如果要在表单中使用BooleanField字段,则需要指定required为False:
- ChoiceField
- 其为选择类型的表单字段,widget默认使用Select。
- choices参数需要一个可迭代的二元组或能够返回可迭代二元组的函数对象。与模型中的choices参数使用方法一样。
- EmailField
- 它继承自CharField,但是提供了Email验证器,用于校验传递的字段值是否是合法的电子邮件地址。widget默认使用EmailInput。
- 除了EmailField之外,表单系统还提供了UUIDField、GenericIPAddressField、URLField等基于CharField的字段类型用于校验特定结构的字符串。
- UUIDField
- 与EmailField类似,不过它只会验证数据是否会空,并会自动将数据生成唯一列,并设置为主键
-
JSONField
- 一个接受 JSON 编码数据的字段,验证给定值是否为有效的 JSON。
- GenericIPAddressField
- 与EmailField类似,不过是验证给定的值是一个有效的 IP 地址。
- URLField
- 与EmailField类似,不过是验证给定值是一个有效的 URL的。
- DateTimeField
- 用于表示时间的表单字段,widget默认使用DateTimeInput。
- 接受一个可选的参数input_formats,这个参数是一个列表,列表元素规定了可以转换为datetime.datetime的时间格式。
- DateTimeField的clean方法接受的值类型可以是datetime.datetime、datetime.date或符合特定格式的字符串,最终会返回datetime.datetime对象或抛出异常。
基于Model定制的表单
将Model翻译成表单是很常见的业务场景,利用Form对象并不难实现,只需要将Model中定义的字段翻译成Form对象中的表单字段即可。但是,如果这种需求很多,且Model中定义的字段也较多,那么重复实现这种表单的过程会很烦琐的。Django表单系统考虑到了这个问题,提供了ModelForm,可以基于Model的定义自动生成表单,很大程度上简化了Model翻译成表单的过程。译成表单字段类型,但是,并不会翻译所有的字段,editable=False的模型字段都不会出现在ModelForm中,如自增主键、自动添加的时间字段等。
class PrettyModelForm(forms.ModelForm):
class Meta:
model = models.PrettyNum
fields = ["name", ]
# fields = "__all__"
# exclude = ['level']
上面代码中就是自动生成了models.PrettyNum模型中的name字段的表单。
常用的Meta选项
- fields
- 其为列表或元组类型,
- 它指定当前的表单应该包含哪些字段,如果要所有的Model字段都包含在表单中,可以设定fields='__all__'。
- ModelForm的定义中必须要包含fields或exclude选项,否则将会抛出异常,同时给出错误提示:Creating a ModelForm without eitherthe'fields'attribute or the'exclude'attribute isprohibited。
- exclude
- 与fields类似,不过是指向当前的表单不应该包含哪些字段,是与fields相反
- labels
- 其为字典类型,用于定义表单字段的名称(输入框左边显示的名称)。表单字段的名称首先会使用Model字段定义设置的verbose_name,如果没有设置,则直接使用字段名。因此当没有定义verbose_name时,就可以使用labels选项来指定字段名。
- help_texts
- 其为字典类型,用于给表单字段添加帮助信息。目前页面中表单字段的帮助信息(输入框下方显示的内容)来自Model字段的help_texts定义,如果没有定义则什么都不显示。help_texts的定义方式与labels选项类似,
- widgets
- 其为字典类型,用于定义表单字段选用的控件。默认情况下,ModelForm会根据Model字段的类型映射表单Field类,因此会应用Field类中默认定义的widgets。这个选项用于自定义控件类型
- field_classes
- 其为字典类型,用于指定表单字段使用的Field类型。默认情况下,对于title字段,ModelForm会将它映射为fields.CharField类型。可以根据需要改变这种默认行为
表单中的常用方法
- is_valid()
- cleaned_data属性
- save()
- 字段值通过校验(is_valid)之后,可以使用ModelForm提供的save方法实现Model对象的保存。
- instance
- 添加表单数据,如果有些数据是不需要用户输入的,需要后台自动生成则使用该方法。
-
form.instance.字段名 = 值
- errors
- 包含了表单的错误信息,这是一个属性,是一个列表格式
- label
- 表示表单的名字,是一个属性,由模型中verbose_name属性控制。
- add_error
注意:使用ModelForm类时,需要先使用该类生成对象。如果需要获取使用ModelForm验证的数据则为:
form = PrettyModelForm(data=request.POST)
PrettyModelForm是类名