django form组件:
校验数据:
校验数据,是后端的Form类对象通过render先渲染到前端,然后浏览器用户输入数据提交到后端,后端根据类中的字段设置的属性来判断数据是否合法。
校验数据的步骤:
第一步需要一个form类,其实就是表单类啦,我们不设置就是text:
class MyForm(forms.Form):
name = forms.CharField(max_length=8,min_length=3,label="用户名",error_messages={
'max_length':"超过了最大长度",
"min_length":"必须大于这个长度",
# "required":"必须输入东西呦思密达"
})
password = forms.CharField(max_length=20,min_length=3,error_messages={
'max_length':"超过长度",
"min_length":"必须大于这个长度",
},widget=widgets.PasswordInput())
第二步是不是该实例化一个对象,没有错:
form_obj = MyForm({'name':'jason'})
注:这一步操做可以在python console中运行,
第三步查看是否合法:
这一步任然可以在python console中运行
form_obj.is_valid()#用于判断什么呢,你输实例化的对象的所有字段是否正常,到字段中找条件啦max_length等看是否满足
第四步:我们可以通过form_obj.errors查看错误信息,这个errorrs是一个字典格式如下:
{
'name': ['Ensure this value has at most 6 characters (it has 7).'],
'password': ['Ensure this value has at least 3 characters (it has 2).'],
'email': ['Enter a valid email address.']
}
第五步查看校验通过的数据
form_obj.cleaned_data #符合条件的都存放到cleaned_data,他是一个字典,可以通过get从中取值,如:
form_obj.cleaned_data..get('"name"')#就能获取到该标签元素的值。
注意:form中所有的字段默认都是必须传值的(required=True),但是你可以设置
password = forms.CharField(max_length=20,min_length=3,required=False)
,那么这样password就可以不必输值。
校验数据的时候可以都传(多传的数据不会做任何的校验>>>不会影响form校验规则)。
总结下:
1.校验顺序:组件校验数据的规则从上往下依次取值校验
2.正确数据的存储位置:校验通过的放到cleaned_data,obj.cleaned_data以字典的形式存放的,通过get取值。
3.错误数据存放的位置:obj.errors中
4.校验是否完全正确:form_obj.is_valid(),true是所有标签中输入的值都满足限制条件max_length等。
5.就是有些标签类对象可以设置不输入(required=False),但是默认都是需要输入的(required=True)
渲染标签:
form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交的按钮呦,需要自己手动添加。
渲染的三种方式
第一种(可扩展性差封装度较高):
{{ form_obj.as_p }}
{{ form_obj.as_ul }}
第二种:注意:form_obj.name.label,不设置属性就是你的对象名字首字母大写,设置值就是你设置的值:
py文件类中的设置:
name = forms.CharField(max_length=8,min_length=3,label="用户名")
form_obj.name以及 form_obj.password都是要渲染的text框默认的是tetxt框:
<form action="">
<p>{{ form_obj.name.label }}{{ form_obj.name }}</p>
<p>{{ form_obj.password.label }}{{ form_obj.password }}</p>
<p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
<input type="submit">
</form>
第三种方式:
py文件:注意呦myform_obj = MyForm()与myform_obj = MyForm(request.POST)必须同名呦,若是不同名,你前端输入的错误数据将也会被清掉,由于有这个myform_obj来保存你输错的信息,如果不同名,那么传入就没有信息传入前端了(前一个对象是总的form对象来存东西的,接收到了信息)。
# 1.生成一个空对象,然后通过接受到的信息对该对象进行实例化
#用户只要传过来的信息都下类中就不管其他的不包含的 ,因为不影响
def reg(request):
myform_obj = MyForm()
if request.method=="POST":
print(request.POST)
# 为什么没有清掉,因为用接收的实例化了它
myform_obj = MyForm(request.POST)
# 前端能够获取前端的数据,并对数据进行判断,因为他们前端的数据都到myform_obj,将上面的myform_obj传入到了前端
if myform_obj.is_valid():
print(myform_obj.cleaned_data)
return HttpResponse("ok")
return render(request,"reg.html",locals())
html文件
<h1>第三种渲染标签的方式</h1>
<form action="">
{% for foo in form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
<input type="submit">
</form>
form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息
在使用form组件对模型表进行数据校验的时候,只需要保证字段一致
那么在创建的对象的时候你就直接**form_obj.cleaned_data
<form action="" method="post" novalidate>
{% for foo in form_obj %}
<p>
{{ foo.label }}{{ foo }}
<span>{{ foo.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit">
</form>
钩子函数:
钩子函数的报错优先级低于类对象中设置的错误的优先级
# 局部钩子函数 (单个字段的校验利用局部钩子函数)
def clean_name(self):
name = self.cleaned_data.get('name')
if '666' in name:
self.add_error('name','光喊666是不行的,要有真实力!')
return name # return还是要加上的,兼容性考虑
# 全局钩子函数 (多个字段的校验利用全局钩子函数)
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password',"两次密码不一致,你这个dsb!")
return self.cleaned_data
展示信息设置标签样式:
from django import forms
from django.forms import widgets
password = forms.CharField(max_length=8,min_length=3,error_messages={
'max_length': '密码最长8位',
'required': '密码不能为空',
'min_length':'密码最少3位'
},widget=widgets.PasswordInput(attrs={'class':'c1 form-control'}))
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()
)
keep = forms.ChoiceField(
label="是否记住密码",
initial="checked",
widget=forms.widgets.CheckboxInput()
)