目录
form组件是django自带的组件,能够自动校验数据,渲染html代码,显示提示信息。非常方便。
form组件的主要功能:
- 校验数据
- 渲染html代码
- 显示错误信息
form组件的基本使用
- 首先导入forms
- 自己创建一个类继承forms.Form
- 在类中自定义字段,这里定义的字段在实际开发中要和前端需要输入的字段相同
from django import forms
class MyForm(forms.Form):
"""
使用form组件
"""
# username必须满足最长8位最短3位
username = forms.CharField(max_length=8, min_length=3)
# password必须满足最长8位最短3位
password = forms.CharField(max_length=8, min_length=3)
# email必须满足邮箱格式
email = forms.EmailField()
form组件校验数据
这里使用测试脚本来测试数据的合法性测试数据只需实例化一个对象,传入需要测试的数据即刻,数据的格式是字典格式
form_obj = MyForm({'username':'wcy', 'password':'1234', 'email':'123@qq.com'})
这里有三个基本的测试方法或属性
form_obj.is_valid() | 查看当前数据是否合法,返回布尔值 |
form_obj.cleaned_data | 查看合法的数据 |
form_obj.errors | 查看不合法的数据,并且返回不合法信息 |
当数据格式完全正确
from app01.views import MyForm
form_obj = MyForm({'username':'wcy', 'password':'1234', 'email':'123@qq.com'})
form_obj.is_valid() #判断数据是否合法
Out[4]: True
form_obj.cleaned_data # 查看合法的数据
Out[6]: {'username': 'wcy', 'password': '1234', 'email': '123@qq.com'}
form_obj.errors # 查看不合法的数据和错误信息
Out[7]: {}
数据部分正确
form_obj = MyForm({'username':'1', 'password':'dfskdf', 'email':'we2'})
form_obj.is_valid() #数据格式有一个不对就是False
Out[9]: False
form_obj.cleaned_data #显示正确数据
Out[10]: {'password': 'dfskdf'}
form_obj.errors #显示错误信息是字典格式,值是列表格式,因为可能有多个约束都不满足
Out[11]:
{'username': ['Ensure this value has at least 3 characters (it has 1).'],
'email': ['Enter a valid email address.']}
数据多传
传入了字段中没有的字段,form组件会自动忽略掉没有的字段
form_obj = MyForm({'username':'sfjaskdf', 'password':'dfskdf', 'email':'we2@qq.com', 'www':'err'})
form_obj.is_valid() #数据多传只判断From中定义的字段 其他忽略
Out[13]: True
form_obj.cleaned_data # 只显示有的字段
Out[14]: {'username': 'sfjaskdf', 'password': 'dfskdf', 'email': 'we2@qq.com'}
form_obj.errors #并没有错误
Out[15]: {}
数据少传
form_obj = MyForm({'username':'sfjaskdf', 'password':'dfskdf'})
form_obj.is_valid()
Out[17]: False # 数据不足报错
form_obj.cleaned_data
Out[18]: {'username': 'sfjaskdf', 'password': 'dfskdf'} #
form_obj.errors # 显示数据不足的错误
Out[19]: {'email': ['This field is required.']} #字段是必须要的
form组件渲染html代码
form组件会自动生成对应字段所需要的html代码,我们只需要直接调用即可。
实现步骤:
1.后端实例化对象并且传递到前端
# 1 生成空对象
form_obj = MyForm()
# 2 传递给html页面
return render(request, 'register.html', locals())
2.前端页面调用生成的代码
前端代码的调用方式有三种,我们只需要在form中使用模板语法调用即刻
(1)第一种,将所有的字段所需的input框全部都渲染
<p>第一种方式将所有的输入框渲染成对应的标签,代码书写少只需一行,扩展性差</p>
{{ form_obj.as_p }} //渲染成p标签
{{ form_obj.as_table }} //table
{{ form_obj.as_ul }} //ul
对应的格式如下
(2)第二种,我们只需要引用对应字段的属性,生成对应的input框。
这里只有一个单独input框,没有label,label需要我们自己取,label的默认值是字段名的首字母大写,我们可以自行的更改。
<p>第二种 扩展性极强,但是当字段较多时,代码量大</p>
<p>lable是字段的标签,可以在创建字段的时候添加label=''属性 label默认的值是字段的首字母大写</p>
{{ form_obj.username.label }}:{{ form_obj.username }}
{{ form_obj.password.label }}:{{ form_obj.password }}
{{ form_obj.email.label }}:{{ form_obj.email }}
更改label的方式是在创建字段的时候加上label属性即可
username = forms.CharField(max_length=8, min_length=3, label='用户名')
(3)第三种,用for循环来渲染,推荐用这种方式
循环实例化的from_obj对象,每一个循环的对象就是一个字段
<p>第三种 代码简单,扩展性强,推荐使用 效果和第二种一样</p>
{% for foo in form_obj %}
<p>{{ foo.label }}:{{ foo }}</p>
{% endfor %}
form组件渲染html代码我们一般使用第三种。
form组件显示提示信息
1.第一步在后端接受前端提交的信息、
def register(request):
"""form组件使用"""
# 1 生成空对象
form_obj = MyForm()
# 2 传递给html页面
if request.method == "POST":
form_obj = MyForm(request.POST) # 只需要将前端传递过来的数据穿到form_obj中 这里名字和前面一致可以保留用户的输入信息
if form_obj.is_valid():
return HttpResponse('验证成功')
return render(request, 'register.html', locals())
如果数据格式验证成功返回验成功的界面
如果验证失败的话,失败的信息会包含在form_obj中,继续返回给前端页面,我们只需要在前端使用模板语法调用即可
注意:在获取前端传来的数据实例化form_obj对象时,这里的对象名字和前面第一次实例化的form_obj名字一样的话,就可以保留用户在页面上输入的信息
2.前端接收错误信息展示
<p>第三种 代码简单,扩展性强,推荐使用</p>
{% for foo in form_obj %}
<p>{{ foo.label }}:{{ foo }}
<span style="color: red">{{ foo.errors.0 }}</span> <!--这里提前定义span标签,用于展示错误信息-->
</p>
{% endfor %}
<input type="submit" class="btn btn-primary">
直接调用errors属性来获取错误信息展示。
自定义报错信息
在定义字段的类中添加error_messages即可,这样报错的信息就是我们自定义的消息。
class MyForm(forms.Form):
"""
使用form组件
"""
# username必须满足最长8位最短3位
username = forms.CharField(
max_length=8, min_length=3, label='用户名',
error_messages={
'max_length': '不能太长,不好',
'min_length': '不能太短,不好',
'required': '不能没有,也不好'
}
)
# password必须满足最长8位最短3位
password = forms.CharField(
max_length=8, min_length=3, label='密码',
error_messages={
'max_length': '不能太长,不好',
'min_length': '不能太短,不好',
'required': '不能没有,也不好'
}
)
confirm_password = forms.CharField(
max_length=8, min_length=3, label='确认密码',
error_messages={
'max_length': '不能太长,不好', # 长度报错
'min_length': '不能太短,不好',
'required': '不能没有,也不好'
}
)
# email必须满足邮箱格式
email = forms.EmailField(
label='邮箱',
error_messages={
'invalid': '格式不对', # 格式不对报错
'required': '不能没有,也不好' # 不存在报错
}
)
钩子函数
- 在特定的节点自动触发完成响应操作
- 钩子函数在forms组件中就类似于第二道关卡,能够让我们自定义校验规则,完成二次校验
- 当用户输入内容满足第一道关卡,钩子函数才会生效
- 钩子函数在定义form组件的类中定义
- forms组件中有两类钩子
- 局部钩子:当需要给一个字段添加校验规则的时候可以使用
- 全局钩子:当需要给多个字段添加校验规则的时候可以使用
- 案例:
- 校验用户名中不能含有666
- 一个字段 用局部钩子
# 钩子函数 只有满足字段的第一道关卡 才会执行
# 局部钩子
def clean_username(self):
username = self.cleaned_data.get('username')
# 判断用户名中是否含有666
# 这里也可以是其他的判断,比如正则判断等
if '666' in username:
self.add_error('username', '666是我的你不能用!') # 添加错误信息
# 钩子函数钩出数据后要返回数据
return username
- 校验密码和确认密码是否一致
- 两个字段用全局钩子
# 全局钩子
def clean(self):
# 全局钩子默认勾出的是所有字段
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
# 判断两次密码是否相等
if password != confirm_password:
self.add_error('confirm_password', '两次密码不一致')
# 返回勾出来的所有数据
return self.cleaned_data
如果用户输入的信息不正确,会添加定义的错误信息
form组件的重要参数介绍
label | 字段名 |
error_messages | 自定义报错信息 |
initial | 默认值 对应input里的value属性 |
required | 控制字段是否必填 |
widget | - form组件的不同类型input的修改 text: widget=forms.widgets.TextInput() password: widget=forms.widgets.PasswordInput() - form组件添加样式 使用attr属性以字典的形式添加,可以添加自定义属性,多个属性用空格隔开 widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2', 'user':'123'}) |
validators | - 校验字段 这是第一道关卡的校验,在钩子函数之前 可以用正则校验,需要导入相应的模块 |
validator字段的使用
from django.core.validators import RegexValidator
phone = forms.CharField(
label='手机号码',
validators=[
RegexValidator(r'^[0-9]{11}', '请输入十一位手机号'), # 正则表达式和错误信息
RegexValidator(r'^182[0-9]{8}', '请输入十一位182开头手机号'),
],
widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
)
form组件中属性在字段中的基本用法的基本用法
# 完整的字段中的用法
username = forms.CharField(
max_length=8, min_length=3, label='用户名', initial='wcy',
error_messages={
'max_length': '不能太长,不好',
'min_length': '不能太短,不好',
'required': '不能没有,也不好'
},
widget=forms.widgets.TextInput(attrs={'class':'form-control'})
)
form组件中的其他字段
需要使用直接copy即可
# 单选字段 radio
gender = forms.ChoiceField(
choices=((1, '男'), (2, '女'), (3, '保密')),
label='性别',
initial=3,
widget=forms.widgets.RadioSelect()
)
# 单选字段 select
hobby = forms.ChoiceField(
choices=((1, '打球'), (2, '撩妹'), (3, '玩')),
label='爱好',
initial=3,
widget=forms.widgets.Select()
)
# 多选select
hobby_1 = forms.MultipleChoiceField(
choices=((1, '打球'), (2, '撩妹'), (3, '玩')),
label='爱好',
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
# 单选的checkbox
keep = forms.ChoiceField(
label='记住密码',
initial='checked',
widget=forms.widgets.CheckboxInput()
)
# 多选的checkbox
hobby_2 = forms.MultipleChoiceField(
choices=((1, '打球'), (2, '撩妹'), (3, '玩')),
label='爱好',
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)