一,检验字段功能
前端写一个form表单,一个按钮用来提交post请求
或者是把前端传来的数据request.post传到类里面进行校验
from django import forms # 为字段增加类以及各种属性 from django.forms import widgets # 抛出异常的时候,返回到页面 from django.core.exceptions import ValidationError class RegForm(forms.Form): # 定义一个属性,可以用来检验字符串类型 name = forms.CharField(max_length=32, min_length=2) pwd = forms.CharField(max_length=32,min_length=2) email = forms.EmailField() def form_test(request): # form里面没有的字段,不会做校验,而且,一旦校验通过数据会都放在cleaned_data里面(放在里面的字段如果不传,校验一定不通过) # 把字典里面的内容,提交到类里面,检验是否符合括号里面的检验条件 form_obj = RegForm({'name': 'lee', 'pwd': '123', 'email': '.com'}) # form_obj.is_valid()返回一个布尔值,True表示所有字段都校验通过,反之校验没有通过 print(form_obj.is_valid()) if form_obj.is_valid(): print(form_obj.cleaned_data) # 校验通过的所有字段 else: print(form_obj.cleaned_data) # print(form_obj.errors) # ErrorDict : {"校验错误的字段":["错误信息",]} print(form_obj.errors.get("name")) # ErrorList ["错误信息",] form_obj = RegForm() return render(request, 'form_test.html', locals())
# 数据从前端传过来进行校验(生成对此昂实例化时,校验字典里面的参数,可以多传但是不可以少传) def form_test(request): if request.method == 'GET': return render(request,'form_test.html') elif request.method =='POST': print(request.POST) myform = RegForm(request.POST) if myform.is_valid(): print(myform.cleaned_data) return HttpResponse('检验成功') else: print(myform.cleaned_data) # 错误信息是一个字典 print(myform.errors) print(myform.errors.as_data()) return HttpResponse('检验失败')
二,组件校验的参数设置
max_length = 最大长度 min_length = 最小长度 label = '用户名' (用于渲染页面时的那三种方式) error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填'}(错误信息) required = True(必须传的值,用于浏览器校验) 在邮箱中包含的一个错误信息:'invalid': '不符合邮箱格式' widget=widgets.TextInput(attrs={'class': 'form-control'})) widgets.xx这里可以设置数据的格式 attrs = {}(大括号里面,可以用字典的格式帮数据添加类名或者其他属性)
三 ,渲染页面的三种方式
<h1>渲染页面的方式一</h1> <form action="" method="post" novalidate> <p>{{ form_obj.name.label }}:{{ form_obj.name }} <span class="pull-right">{{ form_obj.errors.0 }}</span></p> <p>密码:{{ form_obj.name }} <span class="pull-right">{{ form_obj.errors.0 }}</span></p> <p>确认密码:{{ form_obj.name }} <span class="pull-right">{{ form_obj.errors.0 }}</span></p> <p>{{ form_obj.re_pwd.label }}:{{ form_obj.name }} <span class="pull-right">{{ form_obj.errors.0 }}</span></p> <input type="submit"> </form> <hr> <h1>渲染页面的方式二(for循环)</h1> <form action="" method="post" novalidate> {% for foo in form_obj %} <p>{{ foo.label }}:{{ foo }}<span class="pull-right">{{ foo.errors.0 }}</span></p> {% endfor %} <input type="submit"> </form> <hr> <h1>渲染页面的方式三</h1> <form action="" method="post" novalidate> {{ form_obj.as_p }} <input type="submit"> </form>
四,渲染错误信息
视图层,直接把生成的对象传到模型层就可以了
def register(request): if request.method=="POST": form=UserForm(request.POST) return render(request,"register.html",locals()) form=UserForm() return render(request,"register.html",locals())
在前端模型层,进行调取错误信息(一般错误在类里面定义出来,然后在前端直接errors.0就可以了)
<form action="" method="post" novalidate> {% for foo in myform %} <p>{{ foo.label }}:{{ foo }} <span>{{ foo.errors.0 }}</span></p> {% endfor %} <input type="submit" value="提交"> <span>{{ all_error }}</span> </form>
五,局部钩子与全局钩子
相同点:1都放在类下面2,都是把数据进行进一步的校验,3,在函数里面都需要进一步的取数据(比如:self.cleaned_data.get('name'))self.cleaned_data.get('数据名')
不同点:
1,局部钩子是把页面中的一个数据进行多加一层校验,而全局钩子是把几个数据关联起来进行校验(比如校验两次密码是否一致)
2,局部钩子返回值是校验的那个数据或者是跑出去异常的信息,而全局钩子的返回值是self.cleaned_data或者是抛出异常的信息
3,局部钩子抛出的异常信息直接按照(foo.errors.0)这样正常取就可以了,全局钩子的异常信息必须下面这样取,在页面中直接打印all_error就可以
all_error = myform.errors.get('__all__') if all_error: all_error = all_error[0]
4,局部钩子定义函数方法的时候,需要校验那个数据(name)则命名clean_数据名[clean_name(self)],而全局钩子直接命名clean(self)就好,然后在函数里面取数据
1),局部钩子:
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError def clean_name(self): val=self.cleaned_data.get("name") ret=UserInfo.objects.filter(name=val) if not ret: return val else: raise ValidationError("该用户已注册!") def clean_tel(self): val=self.cleaned_data.get("tel") if len(val)==11: return val else: raise ValidationError("手机号格式错误")
2)全局钩子
def clean(self): pwd=self.cleaned_data.get('pwd') r_pwd=self.cleaned_data.get('r_pwd') if pwd and r_pwd: if pwd==r_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致') else: return self.cleaned_data
获取全局钩子抛出的异常:(如果异常存在的话,则需要把异常[0]取出来,这里不做处理也可以,在前端页面上.0取就好)
all_error=my_form.errors.get('__all__') if all_error: all_error = all_error[0]