12月14日学习内容整理:FORM组件
一、form组件的应用场景:
form表单提交数据时我们应该对用户输入的内容和格式等进行验证,若我们自己来写这样的验证功能,就会很繁琐并且会有耦合问题,所以Django为我们封装了一个form组件,专门来干验证这件事
二、Django中的form组件如何进行验证,用Django来创建一个form表单
1、引入:form组件其实是一个Form类
from django import forms
2、自己定义一个类:继承forms.Form
class LoginForm(forms.Form):
3、自己定义要检验的字段:
user=forms.CharField() 要求输入的必须是字符串
pwd=forms.CharField()
usersss = forms.MultipleChoiceField() 多选框,ChoiceField()是单选
还有日期,浮点,数字,email类型等
4、到这一步其实我们已经创建出了一个form组件
5、下面说一下定义字段时的参数
举例:这就是一个简单创建出来的form组件,拥有两个字段
class LoginForm(forms.Form): user=forms.CharField( min_length=5,max_length=12, error_messages={ "required":"该字段不能为空", "min_length":"该字段的长度不能小于5", "max_length":"该字段的长度不能大于12"}, widget=widgets.TextInput(attrs={"class":"form-control"}) ) pwd=forms.CharField( error_messages={ "invalid": "必须是数字" }, widget=widgets.PasswordInput(attrs={"class":"form-control",}) )
》》》》参数
1)min_length=5,max_length=12 规定了长度的范围
2)error_messages={} 指的是当校验失败时,我们应该把错误信息发送给前端,再由前端在页面显示,但是form组件的错误信息默认是英文的,这个参数就可以让我们自己去设置某个错误发生时的提示信息,里面的key是错误类型,value值是提示信息
比如:
min_length 指的是长度过小
max_length 指的是长度过大
required 指的是用户输入的内容为空
invalid 指的是输入的内容格式错误,比如说要求是数字类型,输入的确是字母;email的格式
3)修改input标签类型:因为字符串类型默认的是text,那password类型
from django.forms import widgets
widget=widgets.PasswordInput(attrs={"class":"form-control",}) 这是指定的是type为password,attrs属性是在模版渲染时为标签加上指定的属性值,这里是class值,也可以是其它的属性
widget=widgets.Select(choices=((1,'男'),(0,'女'),)) 这是给select标签添加option标签,整体是一个元组,里面的元素是一个个元组代表一个个option标签,第一个值是option的value值,第二个值是option的文本(也就是下拉菜单显示的内容)
(4)针对多选框:
initial=[2, ],
choices=((1, '上海'), (2, '北京'),), 指定value值和文本
widget=widgets.CheckboxSelectMultiple 指定input标签是checkbox类型
6、form对象,这个很重要
现在我们已经在后端创建出了一个用来检验用户输入内容的form组件,那问题一是要检验前提是我要得到用户输入的内容,二是前端如何渲染,三是校验出的错误信息如何提交给前端,前端怎么显示,这些要用到form对象
(1)实例化
》》》未绑定的表单实例:意思就是这个对象没有相关联数据
login_form1=LoginForm()
》》》绑定的表单实例:意思是指这个对象保存着form提交的数据和校验的错误信息
login_form2=LoginForm(request.POST) 前端form表单是请求格式是post
(2)用未绑定的表单实例对象login_form1传递给模版,模版渲染时就可以用句点符调用我们定义的需要校验的字段,就会渲染出相应的form表单中的标签,我们不能自己在模版中写input输入框,因为这样的输入框传来的值form组件是不认得的,只有form组件自身创建的form表单标签传入的值form组件才会进行校验,否则form组件是不认识这些数据的,也就无法进行校验
(3)用户输入完后前端form表单提交数据后,后端用绑定的表单实例对象login_form2来接受这个数据
注意:::这个对象只会将数据传入对应的字段,也就是只对应类中定义的字段,其它的字段都会忽略掉,比如csrf跨域请求字段,因为类中规定的字段没有那么form组件就会忽略它,也就不会对他进行校验,实际上我们也不需要
(4)校验方法
login_form2.is_valid() 这个方法就是form组件真正要做校验这件事,注意是校验所有的字段,若所有字段都通过了就返回true,只要有一个字段的某一个校验规则不通过就返回false,内部原理大致是按照我们定义的字段顺序,有序的循环每一个字段的每一个校验规则进行校验,一个字段校验完了才校验下一个字段
(5)取出用户输入的字段值:用绑定的表单实例对象调用
》》》肯定可以用request.POST来取,但是这样没有意义,因为我们无法知道哪个字段是校验成功还是失败的
》》》form组件给我们提供了两个属性来分别拿到校验成功的字段和校验失败的字段
login_form2.cleaned_data 保存所有校验成功的字段名和对应的用户输入的内容,是一个字典
login_form2.errors 保存所有校验失败的字段名和相应的错误信息,是一个字典
以上两个方法我们都可以用get(key)来取到对应的内容或者错误信息
注意注意注意::::errors中字段对应的value值是一个列表,里面是一个个错误信息,因为用户输入的内容可能同时不符合多个规则
(6)取出值以后我们就可以调用数据库来判断用户输入的正不正确,比如登录,注册之类的功能
(7)对于错误信息的处理
我们得到errors这个数据后,可以把login_form2.errors 传给前端,前端用句点符调用字段再.0就可以显示出第一个错误信息,这样让用户依次修改
7、钩子:除了规定好的规则外,我们可以额外的对某一个字段或者多个字段进行别的校验
(1)局部钩子
引入:from django.core.exceptions import ValidationError
方法名必须是clean_字段名,执行is_valid()时自动触发执行,但一定要注意局部钩子是在for循环中校验完之前所有的规则后再执行钩子的校验,所以无法取到所有的字段值,所以不能对多个字段进行校验,故叫局部钩子
特别要注意:校验成功以后一定要return对应的字段值给cleaned_data ,如果没有return,该字段对应的就是None,校验失败的话主动触发异常,这个错误信息就会存到errors中,key就是对应的字段名
def clean_user(self): print("============",self.cleaned_data.get("pwd")) # ============ None if not self.cleaned_data.get("user").isdigit(): return self.cleaned_data.get("user") else: raise ValidationError("该字段不能是纯数字") def clean_pwd(self): print("-----------------",self.cleaned_data.get("user")) import re val=self.cleaned_data.get("pwd") ret=re.findall("^\d{6}yuan$",val) if ret: return val else: raise ValidationError("密码不符合设定要求")
(2)全局钩子
方法名必须是clean,指的是for循环结束以后也就是所有字段校验结束以后,这时我就可以拿到所有的字段值,就能够对多个字段值进行校验,这就用到了全局钩子
一定要注意:::校验成功后一定要return cleaned_data,若没有返回值,那么整个cleaned_data就为None,
校验失败的话要主动触发异常,错误信息就会存到errors中,key是_ _all_ _,value值是错误信息
def clean(self): if self.cleaned_data.get("user") and self.cleaned_data.get("pwd"): if self.cleaned_data.get("user") != self.cleaned_data.get("pwd"): return self.cleaned_data else: raise ValidationError("用户名与密码不能一致!") return self.cleaned_data