一、Form表单验证:
原理:在Form表单提交到Views后台时,利用Django特有的验证模版技术(实质上实现验证功能的类)对表单数据进行验证,然后将结果返回到页面上。
html页面代码如下:
<form method="post" action="/login.html">
<p>
<input type="text" name="user" placeholder="用户名">
<!与后台绑定的用户名错误信息>
<span>{{ obj_login_form.errors.user.0 }}</span>
</p>
<p>
<input type="text" name="email" placeholder="邮箱">
<!与后台绑定的邮箱错误信息>
<span>{{ obj_login_form.errors.email.0 }}</span>
</p>
<input type="submit" value="提交">
</form>
后台views代码:
from django import forms
class Login_Form(forms.Form):
# 与前台名称一致的用户名字段,Django内置的普通str验证方法,增加验证最小长度为3
user=forms.CharField(min_length=3)
# django内置的Email验证方法
email=forms.EmailField()
def login(req):
if req.method=='GET':
return render(req,'login.html')
elif req.method=='POST':
# 将表单数据放入Login_Form中
obj_login_form=Login_Form(req.POST)
# 通过is_valid()方法验证,返回是否有错误信息
if obj_login_form.is_valid():
# 当验证通过后打印通过的数据
print(obj_login_form.clean())
else:
# 打印验证失败的错误信息
print(obj_login_form.errors)
return render(req,'login.html',{'obj_login_form':obj_login_form})
注意:
定义的验证类中验证的字段名与前台页面需要验证的字段名必须一致。Django实现了前台模版调用后台内容为空时自动忽略,因此在get请求时即使没有将{'obj_login_form':obj_login_form}传给前台页面,也不会报错。
当前验证效果:
将验证错误信息改为中文,验证模版代码需要修改为如下:
from django import forms
class Login_Form(forms.Form):
# 与前台名称一致的用户名字段,Django内置的普通str验证方法,增加验证最小长度为3
user=forms.CharField(min_length=3,error_messages={'required':'用户名不能为空','min_length':'用户名长度不能小于3'})
# django内置的Email验证方法
email=forms.EmailField(error_messages={'required':'用户名不能为空','invalid':'邮箱格式有误'})
实现验证完后页面刷新也不请空数据,需做以下两处修改:
后台Get请求时调用空的验证类:
if req.method=='GET':
obj_login_form=Login_Form()
return render(req,'login.html',{'obj_login_form':obj_login_form})
前台将<input>标签改为Django自动生成的,代码如下:
<form method="post" action="/login.html">
<p>
<!"用户名">
{{ obj_login_form.user }}
<!与后台绑定的用户名错误信息>
<span>{{ obj_login_form.errors.user.0 }}</span>
</p>
<p>
<!"邮箱">
{{ obj_login_form.email }}
<!与后台绑定的邮箱错误信息>
<span>{{ obj_login_form.errors.email.0 }}</span>
</p>
<input type="submit" value="提交">
二、Ajax方式实现:
原理:通过Ajax将数据提交到后台,后台返回json类型的错误数据展现在前台页面上。
后台返回的错误信息定义如下:
error_list={'status':True,'errors':None}
html代码如下:
<body>
<form id="f1">
<p>
<input type="text" name="user" placeholder="用户名">
</p>
<p>
<input type="text" name="email" placeholder="邮箱">
</p>
<input type="button" value="提交" id="btn_sumit">
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(function () {
$('#btn_sumit').click(function () {
$.ajax({
url:'/ajax_login.html',
type:'post',
//将form表单的数据序列化后传给后台
data:$('#f1').serialize(),
dataType:'json',
success:function (arg) {
console.log(arg);
}
})
})
})
</script>
</body>
验证类实例对象的错误列表errors有多种形式,常用的转换方法有as_json()和as_data()。
1、当使用as_json()时,由于返回给前台的错误信息是json里又套了一层json,因此前台js需要做json解析。
后台代码如下:
import json
def ajax_login(req):
if req.method == 'GET':
return render(req, 'login_js.html')
elif req.method == 'POST':
error_list={'status':True,'errors':None}
# 将表单数据放入Login_Form中
obj_login_form = Login_Form(req.POST)
# 通过is_valid()方法验证,返回是否有错误信息
if obj_login_form.is_valid():
# 当验证通过后打印通过的数据
print(obj_login_form.clean())
else:
error_list['status']=False
# 将错误信息转换为json格式
error_list['errors']=obj_login_form.errors.as_json()
# 将返回到前台的数据转换为json
return HttpResponse(json.dumps(error_list))
前台js代码如下:
<script>
$(function () {
$('#btn_sumit').click(function () {
$.ajax({
url:'/ajax_login.html',
type:'post',
//将form表单的数据序列化后传给后台
data:$('#f1').serialize(),
dataType:'json',
success:function (arg) {
if(arg.status){
console.log('无验证错误信息')
}
else {
//由于后台返回的值是json中套json,因此此处需要再做一次json解析
var error_list=JSON.parse(arg.errors)
//循环遍历错误列表,自动生成span标签承载错误信息
$.each(error_list,function (itemName, item) {
var span= document.createElement('span');
span.innerHTML=item[0].message;//获取第一条错误信息
$('input[name='+itemName+']').after(span);
})
}
}
})
})
})
</script>
2、当使用as_data()时,由于error_list['errors']['email'][0]的类型是'django.core.exceptions.ValidationError',因此需要做一次json转换,完整代码如下:
import json
def ajax_login(req):
if req.method == 'GET':
return render(req, 'login_js.html')
elif req.method == 'POST':
error_list={'status':True,'errors':None}
# 将表单数据放入Login_Form中
obj_login_form = Login_Form(req.POST)
# 通过is_valid()方法验证,返回是否有错误信息
if obj_login_form.is_valid():
# 当验证通过后打印通过的数据
print(obj_login_form.clean())
else:
error_list['status']=False
# 将错误信息转换为json格式
error_list['errors']=obj_login_form.errors.as_data()
print(type(error_list['errors']),error_list['errors']) #error_list['errors']['email']
print(type(error_list['errors']['email']),error_list['errors']['email'])#<class 'list'> [ValidationError(['用户名不能为空'])]
print(type(error_list['errors']['email'][0]),error_list['errors']['email'][0])#<class 'django.core.exceptions.ValidationError'> ['用户名不能为空']
# 将返回到前台的数据转换为json
return HttpResponse(json.dumps(error_list,cls=error_json_encoder))
from django.core.exceptions import ValidationError
class error_json_encoder(json.JSONEncoder):
def default(self, o):
if isinstance(o,ValidationError):
# 如果是ValidationError类型,则将其转换为字典
return {'code':o.code,'message':o.message}
else:
# 如果不是则调用父类方法
return super(error_json_encoder,self).default(self,o)
由于后台返回的json只有一级,因此前台js无需再转换为json对象再处理,因此前台js为:
<script>
$(function () {
$('#btn_sumit').click(function () {
$.ajax({
url:'/ajax_login.html',
type:'post',
//将form表单的数据序列化后传给后台
data:$('#f1').serialize(),
dataType:'json',
success:function (arg) {
if(arg.status){
console.log('无验证错误信息')
}
else {
var error_list=arg.errors;
//循环遍历错误列表,自动生成span标签承载错误信息
$.each(error_list,function (itemName, item) {
var span= document.createElement('span');
span.innerHTML=item[0].message;//获取第一条错误信息
$('input[name='+itemName+']').after(span);
})
}
}
})
})
})
</script>
完整源码请见: