表单介绍
HTML表单负责接收用户的输入,对输入进行合法格式判断,并将数据发送到服务器。一个HTML表单必须指定两样东西:发送数据的url地址,发送的HTTP方法(GET、POST)。
GET方法:将用户数据以?<键1>=<值1>&<键2>=<值2>&...形式拼接到url后面,通常用于请求数据、网页搜索的表单。
POST方法:组合表单的数据并进行编码,然后打包发送到服务器,数据不会出现在url中,通常用于保密信息的发送、大量数据的表单、二进制数据。
在input标签中
#对于form表单也是一样,如果前端不指定post方法,默认使用get方法。
表单字段(常用)
CharField
渲染类型:TextInput
输入空值的返回:empty_value设定的值
转换为对象:Unicode对象
验证:min_length,max_length(如果设置过)
可用的错误信息键:min_length,max_length,required
max_length:允许输入的最大长度
min_length:允许输入的最小长度
strip:默认为True,表示去除前后的空格
empty_value:输入为空时返回的值,默认为空字符串
EmailField
渲染类型:EmailInput
输入空值的返回:空字符串
转换为对象:Unicode对象
验证:用正则表达式验证表单的值,必须是合法邮件地址
可用的错误信息键:required,invalid
max_length:允许输入的最大长度
min_length:允许输入的最小长度
表单字段的参数
error_messages
error_messages={‘key’: ‘value’}
自定义错误提示信息,键是表单里同名的错误类型字符串,值是自定义的提示信息字符串。
其中的key包括:
required,无填写内容
invalid,非法字符
maxlength,超出长度上限
max_length
最大长度
min_length
最小长度
required
required=True/False
该字段必填/非必填。
当为True时,<表单对象>.clean(‘‘)和<表单对象>.clean(None)返回ValidationError异常。
当为False时,<表单对象>.clean(‘‘)和<表单对象>.clean(None)返回None。
label
label=’<显示值>’
字段渲染成HTML代码的提示词,默认在后面加冒号。
如字段name = forms.CharField(label=’Your Name’),显示为HTML的
label_suffix
label_suffix=’<字符>’
自定义字符,代替label生成显示值后面的冒号。
initial
initial=’<值>’
为表单元素定义初始值,即标签中的value=,可传入值和对象。
# initial不会作为数据提交,表单仍需要用户填写数据。
只能用initial传递初始值,如果在渲染表单的时候传递一个初始值字典,会触发表单的验证,此时输出的HTML页面可能包含验证错误。
widget
widget=
指定渲染Widget时使用的widget类,即前端中的type类型。
可用attr参数传入一个字典,对widget添加CSS样式,如:
name = forms.CharField(widget=forms.TextInput(attrs={‘class’: ‘special’}) )
comment = forms.CharField(widget=forms.TextInput(attrs={‘size’: ‘40’}) )
help_text
help_text=’<文本>’
设定辅助性描述文本,相当于HTML的默认显示值。
validators
validators=[ ]
传入列表,包含对字段验证的函数,自定义验证方法的时候用。
localize
实现表单数据输入的本地化。
disabled
disabled=True/False
设置对字段禁用/启用编辑,禁用编辑后,即使非法篡改前端页面的属性向服务器提交,该字段值也会被忽略。
表单API
绑定数据的表单能够验证数据,然后生成HTML表单,未绑定的表单无法验证数据,可生成HTML空表单。
创建空表单:f = <表单名>form()#创建表单类的实例
表单绑定数据:data = {:}#字典键是表单的字段名,值是传入的数据
f = <表单名>form(data)
#传入空字典将创建一个数据为空的已绑定表单
forms.Form实例的数据无法自读,所以创建表单对象之后不可更改。
表单的绑定
<表单对象>.is_bound
判断表单是/否绑定了数据,返回True/False。
表单的数据错误验证
<表单对象>.is_valid()
验证表单数据合法性,返回True/False。.is_valid()实际就是检查<表单对象>.errors是否为空,如果errors列表为空,就把所有数据储存到<表单对象>.cleaned_data字典中。
<表单对象>.errors
包含所有错误信息的字典类型,键是表单字段名,值是由错误信息组成的字符串形列表。
<表单对象>.errors.as_data()
返回错误信息的字典形式,将字段映射到原始的ValidationError实例,如:
{'sender': [ValidationError(['Enter a valid email address.']) ],
'subject': [ValidationError(['This field is required.']) ] }
<表单对象>.errors.as_json()
错误信息字典的JSON序列化形式,如:
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}] }
<表单对象>.add_error(<字段名>, <错误信息>)
向表单的指定字段添加错误信息。
<表单对象>.has_error(<字段>, code=xxx)
判断某个字段是/否有指定的xxx错误,返回True/False。当code=None时,该字段有任何错误都返回True。
<表单对象>.non_field_errors()
返回<表单对象>.errors中不是与特定字段关联的错误。
表单的cleaned_data数据
①如果数据验证通过,把所有数据储存到<表单对象>.cleaned_data字典中;如果数据验证不通过,只把合法的数据存到<表单对象>.cleaned_data字典中。
②cleaned_data只包含Form类中的字段,如果传递额外数据,将不被储存。
③传递的数据不包含Form类中的某字段,cleaned_data中依然包含该键值对,显示为空值。
表单的数据更改验证
<表单对象>.has_changed()
检查表单数据是否从初始值发生改变,有改变返回True,无改变返回False,如:
data = <字典>
f = ContactForm(request.POST, initial=data) # POST和data内容不一样
f.has_changed()
<表单对象>.changed_data
返回表单中有数据变化的字段的列表,如:
f = ContactForm(request.POST, initial=data) # POST和data内容不一样
print(“, “.join(f.changed_data) )
表单的HTML生成
form类不包含
标签和提交按钮,为方便开发人员自行编写控制表单动作和CSS,JS及如bootstrap框架的嵌入。生成HTML标签的就是表单字段名,每个字段类型都由一个默认的HTML标签展示,可用widget参数指定生成的类型。
表单自动为每个input元素设置一个,用于的for参数。
{{ form.as_p }}
将每个字段渲染成标签。
{{ form.as_ul }}
将每个字段渲染成
标签(无序),
{{ form.as_table }}
将表单的每个字段渲染成标签,标签需自己指定。
表单字段在前端的属性
{{ field.value }} 当前字段的值,比如一个Email字段的值:[email protected]
{{ field.errors }} 包含错误信息的元素
{{ field.label }} 字段的label信息
{{ field.id_for_label }} 自定义字段标签的id
{{ field.html_name }} 指定字段生成的input标签中name属性的值
{{ field.help_text }} 字段的帮助信息
{{ field.is_hidden }} 用于判断当前字段是否为隐藏的字段,隐藏则返回True
{{ field.field }} 返回字段的参数列表,例如{{ char_field.field.max_length }}
表单错误信息的CSS样式
class <表单名>FORM(forms.Form):
error_css_class = ‘error’
required_css_class = ‘required’
#其它表单字段...
以后这个表单渲染HTML时将自动为error行和required行添加对应的CSS样式。
表单上传文件
没看懂,略。。。
模型表单ModelForm
基于model模型创建的表单,对模型的字段进行重用,根据model字段的限制进行表单验证。
验证后,ModelForm.save()实际就是调用Model.save(),直接保存到数据库。
from django.forms import ModelForm
from <应用名>.models import <类>
class <类名>Form(ModelForm): #继承于ModelForm类
class Meta: #设置元类Meta
model = <类> #设置model属性为某个模型类
fields = [<字段1>, <字段2>, ...] #用field属性传入列表,指定类中的字段
fields = ‘__all__’ #也可用field属性传入类的全部字段
exclude = [<字段1>, <字段2>, ...] #用exclude属性将排除的字段之外全部传入
模型表单的保存
<模型表单对象>.save(commit=True) #将form表单的内容提交到数据库并保存
如果没有commit=True就只提交,不保存
指定数据对象
form = ModelForm(instance=<绑定的Model对象>)
此时可以直接form.save()将表单数据保存到数据表中。
#如果不指定某个对象,save()时会在数据表中新增一行数据
模型字段对应表单字段
Model Form
AutoField 无对应
BigAutoField 无对应
BigIntegerField IntegerField
CharField 相同,如果model设置null=True,Form将使用empty_value
CommaSeparatedIntegerField CharField
ForeignKey ModelChoiceField
ManyToManyField ModelMultipleChoiceField
PositiveIntegerField IntegerField
PositiveSmallIntegerField IntegerField
SmallIntegerField IntegerField
TextField CharField,属性widget=forms.Textarea
模型字段设置blank=True属性,表单字段将设置required=False,反之相反。
模型字段的verbose_name属性会设为表单字段的label属性,并将第一个字母大写。
模型字段设置editable=False属性,表单类中将不会出现该字段,因为该字段不可编辑。
模型字段的help_text属性即为表单字段的help_text属性。
模型字段设置choices参数,表单字段的widget属性将设置为Select,其选项和模型字段相同。表单选项中通常会包含一个空选项作为默认,如果该字段必选,会强制用户选择一个选项;如果模型字段具有default参数,就不会在表单选项中添加空选项。
模型表单的验证
用.is_valid()方法或查询.errors列表,也可以重写模型表单的def clean()方法进行额外的验证,如:
class <类名>Form(ModelForm):
class meta:
# ...
def clean_<函数名>(self):
#验证self.cleaned_data字典的数据...
return <数据>
自定义ModelForm字段
使用元类Meta的widgets属性:
class <类名>Form(ModelForm):
class Meta:
model = <类>
fields = [‘<字段1>’, ...]
widgets = { #传入字典,键是模型字段名,值是自定义的内容
‘<字段1>’:Textarea(attrs={‘cols’:80, ‘rows’:20} ),
...
}
ModelForm字段的本地化
使用Meta类的localized_fields属性,传入一个元组,指定本地化的字段:
class <类名>Form(ModelForm):
class meta:
model = <类>
localized_fields = (‘<字段1>’, ...) #传入’__all__’表示将类中的所有字段本地化
表单示例
①在forms.py中:
from django import forms
class <表单名>Form(forms.Form): #所有表单继承于forms.Form类
sender = forms.EmailField()
name = forms.CharField(label=’Your Name’, max_length=100)
#一个字段代表中的一个元素,字段负责验证和转换数据
# label用于设置说明标签,这里的max_length同时限制前端和后端的输入长度
②在views.py中:
from .forms import <表单名>Form
def get_name(request):
if request.method == ’POST’: #对于POST方法发送数据,接收数据并验证、处理
a_form = <表单名>Form(request.POST)
#用request.POST字典构造forms.Form类实例,将所有数据加载到表单中
if a_form.is_valid():
#处理表单数据...
return HttpResponseRedirect(‘/xxx/’) #处理成功,重定向到一个新url
if request.method == ’GET’: #对于GET方法请求数据,返回空表单到模板
a_form = <表单名>Form()
return render(request, ‘xxx.html’, {‘form’: a_form}
#处理不成功时,给用户返回这个模板。如果数据不合法,逻辑会在if a_form.is_valid()处断开,
此时的a_form是包含原数据的表单,方便用户修改
③在templates中:
{{ form.<字段名> }} 获取表单的字段内容,用于手动渲染表单
{{ form.<字段名>.label_tag }} 生成
{{ form.hidden_fields }} 表单中的不可见字段的集合
{{ form.visible_fields }} 表单中的可见字段的集合
表单模板的重用
将表单模板保存为一个独立HTML文件,然后用{% include %}引用:
{% include ‘xxxform.html’ %}
{% for field in form %}
#处理字段...
{% endfor %}
用with参数给表单取别名,防止名称冲突:
{% include ‘xxxform.html’ with form=<别名> %}
{% for field in <别名> %}
#处理字段...
{% endfor %}