FORMS组件
前奏
当我们在一个网页注册信息的时候,会有一些提示信息,这些提示信息是如何展示在页面的呢?
小例子:
前端
<form action="" method="post">
<p>username: <input type="text"></p>
<span style="color: red">{{ back_msg.username }}</span>
<p>password: <input type="password"></p>
<span style="color: red">{{ back_msg.password }}</span>
<input type="submit" value="确定">
</form>
后端
def reg(request):
back_msg = {'username':'','password':""}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if '啊啊' in username:
back_msg['username'] = '不符合条件'
if len(password)<3:
back_msg['password'] = '密码太短了'
return render(request,'reg.html',locals())
有人会问数据的校验为什么不在前端取完成呢,前端的校验数据可有可无,如果你在前端校验,人家可以直接修改,绕过前端抽后端提交数据,所以必须在后端完成数据的校验
基本使用
from django import forms
class RegForm(form.Form):
username = forms.CharField(min_length=3,max_length=8)
password = forms.CharField(min_length=3,max_length=8)
email = forms.EmailField()
数据的校验
from app01 import forms
reg_form = forms.RegForm({'username':'zc','password':'....','email':'123'})
reg_form.is_valid() # 判断是否合法
False
reg_form.cleaned_data # 查看所有通过校验的数据
{'username':'zc','password':'....'}
reg_form.errors # 查看所有不符合校验规则以及原因
{
'email': ['Enter a valid email address.']
}
但是校验数据类中出现的字段,你多传了不会有影响,直接忽略,但是你少,你在校验数据的时候就会是False
渲染标签
forms组件会帮你渲染用户输入的标签,不能帮你渲染提交按钮
第一步:
def reg(request):
reg_form = forms.RegForm() # 先产生一个空对象
return render(request,'reg.html',locals())
第二步
{# 第一种渲染方式 #}
{{ reg_form.as_p }}
{{ reg_form.as_ul }}
{{ reg_form.as_table }}
{# 第二种方式 #}
{{ reg_form.username.label }}:{{ reg_form.username }}
{{ reg_form.password.label }}:{{ reg_form.password }}
{{ reg_form.email.label }}:{{ reg_form.email }}
{# 第三种 #}
{% for foo in reg_form %}
{{ foo.label }}:{{ foo }}
{% endfor %}
第一种封装性太高,不利于扩展,第二种代码量太多,我们可以使用第三种,扩展性也高
展示校验的提示信息
如果不想让前端帮你做校验信息,<form action="" method="post" novalidate>
加上这个
<form action="" method="post" novalidate>
{% for foo in reg_form %}
{{ foo.label }}:{{ foo }}
<span style="color: red">{{ foo.errors.0 }}</span>
{% endfor %}
<input type="submit">
后端:
def reg(request):
reg_form = forms.RegForm() # 1. 先产生一个空对象
if request.method == 'POST':
# 获取用户数据并且校验
"""
1.数据获取繁琐
2.校验数据需要构造成字典的格式传入才行
ps:但是request.POST可以看成就是一个字典
"""
reg_form = forms.RegForm(request.POST)# 3.校验数据
if reg_form.is_valid():# 4. 判断是否合法,合法执行下面的,操作数据存储数据
return HttpResponse('OK')
# 直接将该空对象传递给html页面
return render(request,'reg.html',locals())
get请求和post传给html页面对象变量名必须一样,forms组件当你的数据不合法的情况下 会保存你上次的数据 让你基于之前的结果进行修改,更加的人性化,但是你前面必须加上一个空对象,校验数据的变量名和产生空对象的变量名一致
针对错误的提示信息我们还可以自己定制
class RegForm(forms.Form):
username = forms.CharField(min_length=4,max_length=32,label='账号',
error_messages=
{'min_length': '最小4位',
'max_length': '最大32位',
'required':'账号不能为空'})
password = forms.CharField(min_length=6,max_length=12,label='密码', error_messages=
{'min_length': '最小6位',
'max_length': '最大12位',
'required':'面膜不能为空'})
email = forms.EmailField(label='邮箱',error_messages={'invalid': '邮箱格式不正确',
'required': '邮箱不能为空'})
HOOK
局部钩子: 当你需要给单个字段增加校验规则的时候可以使用
def clean_username(self):
# 获取用户名
username = self.cleaned_data.get('username')
if '666' in username:
# 提示前端展示错误信息
self.add_error('username','老铁666,不刷礼物吗')
# 将钩子函数勾出来的数据再放回去
return self.username
全局钩子:当你需要给多个字段增加校验规则的时候可以使用
如:校验密码和确认密码是否一样
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not confirm_password == password:
self.add_error('confirm_password','两次密码不一致')
# 将钩子函数钩出来数据再放回去
return self.cleaned_data
补充
label 字段名
error_messages 自定义报错信息
initial 默认值
required 控制字段是否必填
"""
1.字段没有样式
2.针对不同类型的input如何修改
text
password
date
radio
checkbox
...
"""
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2'})
# 多个属性值的话 直接空格隔开即可
# 第一道关卡里面还支持正则校验
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
]
其他渲染类型
# 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()
)
# 多选
hobby1 = 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
hobby2 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)