1.form组件的校验功能
文件formsdemo
models
from django.db import models # Create your models here. class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.EmailField() tel=models.CharField(max_length=32)
views
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms class UserForm(forms.Form): #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写 name = forms.CharField(min_length=4) pwd = forms.CharField(min_length=4) r_pwd = forms.CharField(min_length=4) email = forms.EmailField() tel = forms.CharField #forms组件的键的名字和这些字段的名字要一致 def reg(request): if request.method == "POST": print(request.POST) #<QueryDict: {'csrfmiddlewaretoken': ['gEVJ683XmW6CKzXzfYDNGLXPuURgOjka6yYUuxGVBp9n1tV78D2APZ1iktJmXKq8'], 'name': ['kris'], 'pwd': ['123'], 'r_pwd': ['123'], 'email': ['1234@qq.com'], 'tel': ['18271182769']}> #form = UserForm({"name":"yu", "email":"123@qq.com", "xxx":"alex" }) #类的实例化,可以给它传参,只会给你校验字段里边有的数值,没有的不会校验,有的校验完后就会返回True;form组件的校验规则是有几个就要写几个,多了无所谓不能少写,而且传来的也要符合字段规则。 form = UserForm(request.POST) #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。 print(form.is_valid()) #返回一个布尔值,只会返回 True or False if form.is_valid(): #都正确 print(form.cleaned_data) #这是全部都是对的键值对{"name":"kris", "email":"123@qq.com"...} else: # print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"} # print(form.errors) #这里放错误的 {"name":["......."]}(如果name校验错了)
##<ul class="errorlist"><li>name<ul class="errorlist"><li>该用户已注册</li></ul></li><li>pwd<ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul></li><li>r_pwd<ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul></li></ul> # print(type(form.errors)) #ErrorDict <class 'django.forms.utils.ErrorDict'> print(form.errors.get("name")) #<ul class="errorlist"><li>该用户已注册</li></ul> print(type(form.errors.get("name"))) #ErrorDict <class 'django.forms.utils.ErrorList'> print(form.errors.get("name")[0]) 该用户已注册 ''' if 所有字段校验成功,则
form.is_valid()
form.cleaned_data:{"name":"kris", "email":"123@qq.com"} 校验都通过之后,所有字段的信息都在这里边。
form.errors ''' return HttpResponse("OK") return render(request, "reg.html") #这是get请求
reg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p>用户名<input type="text" name="name"></p> <p>密码<input type="password" name="pwd"></p> <p>确认密码<input type="password" name="r_pwd"></p> <p>邮箱<input type="text" name="email"></p> <p>手机号<input type="text" name="tel"></p> <input type="submit"> </form> </body> </html>
2.渲染标签
reg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} <p>用户名<input type="text" name="name"></p> <p>密码<input type="password" name="pwd"></p> <p>确认密码<input type="password" name="r_pwd"></p> <p>邮箱<input type="text" name="email"></p> <p>手机号<input type="text" name="tel"></p> <input type="submit"> </form> <hr> // <h3>forms组件的渲染方式1</h3> //form表单的name值,应该与forms组件的字段的名字一致;django的forms组件怕你写的不一致,这里才有了渲染的功能;是get请求的时候 <form action="" method="post"> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }} </p> <p> {{ form.pwd.label }} {{ form.pwd }} </p> <p> 确认密码 {{ form.r_pwd }} </p> <p>邮箱{{ form.email }}</p> <p>手机号{{ form.tel }}</p> <input type="submit"> </form> <h3>forms组件渲染方式2</h3> // 渲染出来的是英文,可以在UserForm这个类里边的字段下添加 label标签写上中文 <form action="" method="post"> {% csrf_token %} {% for field in form %} //for循环这个form;拿到这个field(每个字段对象,等同与上面方式一的form.name、form.pwd...) <p> <label for="">{{ field.label }}</label> //每个字段里边加上自己label就可以了,label标签可以跟下面的关联起来。 {{ field }} </p> {% endfor %} <input type="submit"> </form> <h3>forms组件渲染方式3</h3> <form action="" method="post"> {# 不灵活,把样式给固定死了,p标签里边放label标签 #} {% csrf_token %} {{ form.as_p }} //调用它下面as_p的方法,它还有as_ul的方法; <input type="submit"> </form> </body> </html>
渲染错误信息
第一个form通过验证已经有一个个的数据了,区别在于它传到reg.html时候,它.name还是input标签,你点提交这个页面没有变;同时它也可以把你传的那个信息给渲染出来作为input标签的value值。
之所以能看到错误信息,是因为我post提交了构建了一个新form页面,在post请求下加了下面这个:
return render(request, "reg.html", locals())
reg.html
<h3>forms组件的渲染方式1</h3> <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }}<span>{{ form.name.errors.0 }}</span> //有错误信息就放,没有就不显示 </p> <p> {{ form.pwd.label }} {{ form.pwd }}<span>{{ form.pwd.errors.0 }}</span> {#这里放错误信息,它自己的errors#} </p> <p> 确认密码 {{ form.r_pwd }}<span>{{ form.r_pwd.errors.0 }}</span> </p> <p>邮箱{{ form.email }}<span>{{ form.email.errors.0 }}</span></p> <p>手机号{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p> <input type="submit"> </form>
views
from django.shortcuts import render, HttpResponse # Create your views here. from django import forms class UserForm(forms.Form): #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写 name = forms.CharField(min_length=4, label="用户名") pwd = forms.CharField(min_length=4, label="密码") r_pwd = forms.CharField(min_length=4,label="确认密码") email = forms.EmailField(label="邮箱") tel = forms.CharField(label="手机号") def reg(request): if request.method == "POST": print(request.POST) #form = UserForm({"name":"yu", "email":"123@qq.com"}) #类的实例化,可以给它传参 form = UserForm(request.POST) #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。 #你这个form已经通过验证传一个个数据了;已绑定数据表单对象的form print(form.is_valid()) #返回一个布尔值 通过校验之后的form if form.is_valid(): #都正确 经过验证之后的form print(form.cleaned_data) #这是全部都是对的{"name":"kris", "email":"123@qq.com"} else: print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"} # print(form.errors) #这里放错误的 {"name":["......."]} # print(type(form.errors)) #ErrorDict # print(form.errors.get("name")) # print(type(form.errors.get("name"))) #ErrorDict # print(form.errors.get("name")[0]) return render(request, "reg.html", locals()) #如果校验失败后,它返回这个页面,可以把第一次输入的信息给保存了,作为value值;它走的是post请求 ''' 之所以post提交后可以保存输入的信息,因为这两个form不是一个 if 所有字段校验成功,则form.cleaned_data:{"name":"kris", "email":"123@qq.com"} ''' #return HttpResponse("OK") get请求是走下面这个 form=UserForm() #未绑定数据表单对象,上边的form是绑定表单对象 #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值 return render(request, "reg.html", locals()) #把值传进来进行渲染;get请求
3.forms组件的参数配置
reg.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> 7 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 8 </head> 9 <body> 10 <div class="container"> 11 <div class="row"> 12 <div class="col-md-6 col-lg-offset-3"> 13 {# <form action="" method="post">#} 14 {# {% csrf_token %}#} 15 {# <p>用户名<input type="text" name="name"></p>#} 16 {# <p>密码<input type="password" name="pwd"></p>#} 17 {# <p>确认密码<input type="password" name="r_pwd"></p>#} 18 {# <p>邮箱<input type="text" name="email"></p>#} 19 {# <p>手机号<input type="text" name="tel"></p>#} 20 {# #} 21 {# <input type="submit">#} 22 {# </form>#} 23 24 <hr> 25 <h3>forms组件的渲染方式1</h3> 26 <form action="" method="post" novalidate> 27 {% csrf_token %} 28 <p>{{ form.name.label }} 29 {{ form.name }}<span>{{ form.name.errors.0 }}</span> 30 </p> 31 <p> 32 {{ form.pwd.label }} 33 {{ form.pwd }}<span>{{ form.pwd.errors.0 }}</span> {#这里放错误信息,它自己的errors#} 34 </p> 35 <p> 36 确认密码 37 {{ form.r_pwd }}<span>{{ form.r_pwd.errors.0 }}</span> 38 </p> 39 <p>邮箱{{ form.email }}<span>{{ form.email.errors.0 }}</span></p> 40 <p>手机号{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p> 41 <input type="submit"> 42 </form> 43 44 {# <h3>forms组件渲染方式2</h3>#} 45 {# <form action="" method="post">#} 46 {# {% csrf_token %}#} 47 {# {% for field in form %}#} 48 {# <p>#} 49 {# <label for="">{{ field.label }}</label>#} 50 {# {{ field }}#} 51 {# </p>#} 52 {# {% endfor %}#} 53 {# <input type="submit">#} 54 {# </form>#} 55 {# #} 56 {# <h3>forms组件渲染方式3</h3>#} 57 {# <form action="" method="post"> {# 不灵活,把样式给固定死了#} 58 {# {% csrf_token %}#} 59 {# {{ form.as_p }}#} 60 {# <input type="submit">#} 61 {# </form>#} 62 63 </div> 64 </div> 65 </div> 66 </body> 67 </html>
views
1 from django.shortcuts import render, HttpResponse 2 3 # Create your views here. 4 5 from django import forms 6 7 from django.forms import widgets 8 class UserForm(forms.Form): #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写 9 name = forms.CharField(min_length=4, label="用户名",error_messages={"required":"该字段不能为空"}, 10 widget=widgets.TextInput(attrs={"class":"form-control"}) 11 ) 12 pwd = forms.CharField(min_length=4, label="密码", 13 widget=widgets.PasswordInput(attrs={"class":"form-control"})) 14 r_pwd = forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"})) 15 email = forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"})) 16 tel = forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"})) 17 18 19 def reg(request): 20 if request.method == "POST": 21 print(request.POST) 22 23 24 #form = UserForm({"name":"yu", "email":"123@qq.com"}) #类的实例化,可以给它传参 25 form = UserForm(request.POST) #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。 26 #你这个form已经通过验证传一个个数据了;已绑定数据表单对象 27 print(form.is_valid()) #返回一个布尔值 28 if form.is_valid(): #都正确 29 print(form.cleaned_data) #这是全部都是对的{"name":"kris", "email":"123@qq.com"} 30 else: 31 print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"} 32 # print(form.errors) #这里放错误的 {"name":["......."]} 33 # print(type(form.errors)) #ErrorDict 34 35 # print(form.errors.get("name")) 36 # print(type(form.errors.get("name"))) #ErrorDict 37 # print(form.errors.get("name")[0]) 38 return render(request, "reg.html", locals()) #如果校验失败后,它返回这个页面 39 ''' 40 if 所有字段校验成功,则form.cleaned_data:{"name":"kris", "email":"123@qq.com"} 41 ''' 42 43 #return HttpResponse("OK") 44 form=UserForm #未绑定数据表单对象 #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值 45 return render(request, "reg.html", locals())
from django.forms import widgets class UserForm(forms.Form): #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写 name = forms.CharField(min_length=4, label="用户名",error_messages={"required":"该字段不能为空"}, //错误信息,required是为空错误 widget=widgets.TextInput(attrs={"class":"form-control"}) #渲染什么标签通过这里告诉我,这个标签有什么属性通过attrs告诉我,form-control样式就变好看了 ) //它默认的就是TextInput类型 pwd = forms.CharField(min_length=4, label="密码", widget=widgets.PasswordInput(attrs={"class":"form-control"})) //变成密文了 r_pwd = forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"})) email = forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"})) tel = forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"}))
4.forms组件校验的局部钩子
views
from django import forms from django.forms import widgets from app01.models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS,ValidationError class UserForm(forms.Form): #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写 name = forms.CharField(min_length=4, label="用户名",error_messages={"required":"该字段不能为空"}, widget=widgets.TextInput(attrs={"class":"form-control"}) ) pwd = forms.CharField(min_length=4, label="密码", widget=widgets.PasswordInput(attrs={"class":"form-control"})) r_pwd = forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"})) email = forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"})) tel = forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"})) 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): #限定手机号11位 val = self.cleaned_data.get("tel") if len(val)==11: return val else: raise ValidationError("手机号格式错误")
5.全局钩子
forms可单独放在一个py文件里边
myforms.py
#Author:Kris from django import forms from django.forms import widgets from app01.models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS,ValidationError class UserForm(forms.Form): #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写 name = forms.CharField(min_length=4, label="用户名",error_messages={"required":"该字段不能为空"}, widget=widgets.TextInput(attrs={"class":"form-control"}) ) pwd = forms.CharField(min_length=4, label="密码", widget=widgets.PasswordInput(attrs={"class":"form-control"})) r_pwd = forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"})) email = forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"})) tel = forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"})) def clean_name(self): ##加一个实例方法 val = self.cleaned_data.get("name") #说明它通过上边name字段那层的校验了 ret = UserInfo.objects.filter(name=val) if not ret: return val #再校验,合格了返回的还是之前的那个val else: raise ValidationError("该用户已注册") def clean_tel(self): val = self.cleaned_data.get("tel") # if len(val)==11: return val else: raise ValidationError("手机号格式错误") 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: #如果pwd和r_pwd有一个为空,说明没检验通过 return self.cleaned_data
views
from django.shortcuts import render, HttpResponse # Create your views here. from app01.myforms import * def reg(request): if request.method == "POST": print(request.POST) #form = UserForm({"name":"yu", "email":"123@qq.com"}) #类的实例化,可以给它传参 form = UserForm(request.POST) #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。 #你这个form已经通过验证传一个个数据了;已绑定数据表单对象 print(form.is_valid()) #返回一个布尔值 if form.is_valid(): #都正确;is_valid帮我们做校验的方法 print(form.cleaned_data) #这是全部都是对的{"name":"kris", "email":"123@qq.com"} else: print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"} #全局钩子错误 #print('errors', form.errors.get('__all__')[0]) #可以写某个字段 --->> 打印: error 两次密码不一致 errors = form.errors.get('__all__') #有name、email字段错了就写name、email,全局错误就写__all__ ;拿到errors交给模板 return render(request, "reg.html", locals()) #如果校验失败后,它返回这个页面 ''' if 所有字段校验成功,则form.cleaned_data:{"name":"kris", "email":"123@qq.com"} ''' #return HttpResponse("OK") form=UserForm() #未绑定数据表单对象 #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值 return render(request, "reg.html", locals())
reg.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-lg-offset-3"> <hr> <h3>forms组件的渲染方式1</h3> <form action="" method="post" novalidate> {% csrf_token %} <p>{{ form.name.label }} {{ form.name }}<span class="pull-right error">{{ form.name.errors.0 }}</span> </p> <p> {{ form.pwd.label }} {{ form.pwd }}<span class="pull-right error">{{ form.pwd.errors.0 }}</span> {#这里放错误信息,它自己的errors#} </p> <p> 确认密码 {{ form.r_pwd }}<span class="pull-right error">{{ form.r_pwd.errors.0 }}</span><span class="pull-right error">{{ errors.0 }}</span> //全局错误信息传到模板里边 </p> <p>邮箱{{ form.email }}<span class="pull-right error">{{ form.email.errors.0 }}</span></p> <p>手机号{{ form.tel }}<span class="pull-right error">{{ form.tel.errors.0 }}</span></p> <input type="submit"> </form> </div> </div> </div> </body> </html>