一、前言
今天我们来用个一个ajax的例子,来说明form的验证,还有一个就是,我们json.dumps的只能是python简单的数据类型,但是如果遇到复杂的数据类型,json.dumps是序列化不了的,那这个怎么办呐。我们用什么办法解决呐,下面我们就来学习一下,这个东西,还有一个就是我们在写,views代码的时候,我们可以另外建一个文件夹,所以我们整体的目录结构如下:
-sday22
-app01 #app名字
migrations #初始化数据库的
views #写业务代码的
- __init__.py
- accounts.py #用户验证
- blogs.py #博客业务代码
- ...
.....
forms #写forms验证的
- __init__.py
- froms.py #专业做forms验证的
- ....
....
- sday22 #项目名
.....
- static #静态资源
....
- templates #模板
...
- manage.py
二、用ajax获取内置序列化错误信息
前提,我们以后的项目编写,都按照上面的目录结构,所以我们的业务代码都是写在view文件夹下的
2.1、路由设置
说明:设置登录的url
from django.urls import path
from app01.views import accounts
urlpatterns = [
path('login/', accounts.login),
]
2.2、视图函数编写
说明:这边要写很多,这边有from验证,django的序列化的转换,以及登录函数login,为了方便我们写在一个文件里面,但是下面是我分3块去写
1、forms验证
from django import forms
from django.forms import fields,widgets
class LoginForm(forms.Form):
username = fields.CharField() #这跟login.html中的input标签的name属性的值一致
password = fields.CharField(
max_length=64,
min_length=12
)
2、定义JsonCustomEncoder类
说明:这个类特意是为了处理无法序列化复杂的数据类型的,上面 result = json.dumps(ret,cls=JsonCustomEncoder) #这边cls 是序列化的时候,对每一个字段序列化的时候,都会调用一个它的default方法,会在下面的login函数中用到
from django.core.exceptions import ValidationError
import json
class JsonCustomEncoder(json.JSONEncoder): #直接在cls=JsonCustomEncoder类名,去序列化复杂的数据类型
def default(self,field):
if isinstance(field,ValidationError): #field是否是ValidationError的一个对象
return {'code':field.code,'messages':field.messages}
else:
return json.JSONEncoder.default(self,field)
3、login函数
说明:序列化的时候,复杂的数据类型,json是处理不了的,所以需要特殊处理,这边要定义个JsonCustomEncoder类
from django.shortcuts import render,HttpResponse
import json
def login(request):
ret = {'status':True,'error':None,'data':None}
if request.method == "GET":
return render(request,'login.html')
elif request.method == "POST":
obj = LoginForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
else:
# print(type(obj.errors))
# ret['error'] = obj.errors.as_json() # as_data 帮我返回的是原生的字典
# print(type(obj.errors.as_data()))
# for k,v in obj.errors.as_data().items():
# print(k,v)
# ret = {'k1':'v1','k2':ValueError()} #像这种复杂数据类型,json是不能序列化的,我们只能做局部处理
#from django.forms.utils import ErrorDict #通过源码得知:as_data 帮我返回的是原生的字典,as_json()是类似json格式的字符串
# print(obj.errors.as_json()) #我拿到一个字符串,把这个字符串添加到error中
# from django.core.exceptions import ValidationError #看一下这个异常
ret['error'] = obj.errors.as_data()
result = json.dumps(ret,cls=JsonCustomEncoder) #这边cls 是序列化的时候,对每一个字段序列化的时候,都会调用一个它的default方法
return HttpResponse(json.dumps(result))
2.3、模板编写
说明:模板我们用ajax去请求,然后收到数据处理
<body>
<form id="fm">
{% csrf_token %}
<p><input type="text" name="username" /></p> #这边username 需要跟 from 里面的字段 是一模一样
<p><input type="text" name="password" /></p>
<a id="submit">提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
$(function(){
$('#submit').click(function(){
$.ajax({
url:'/login/',
type:'post',
data:$('#fm').serialize(),
sucess:function(arg){
//console.log(arg);
arg = JSON.parse(arg);
console.log(arg)
},
error:function(){
}
})
})
})
</script>
</body>
最后返回的数据类型为:
"{\"data\": null, \"status\": true, \"error\": {\"username\": [{\"code\": \"required\", \"messages\": [\"This field is required.\"]}],
\"password\": [{\"code\": \"required\", \"messages\": [\"This field is required.\"]}]}}"
三、总结
- python中的json函数,只能处理 简单的 数据类型,如果要处理复杂的数据类型,比如:datetime、ValidationError等这种复杂的数据类型,需要协助定义:
JsonCustomEncoder
类,然后json.dumps(ret,cls=JsonCustomEncoder)去引用 - python还有其他的复杂的序列化操作:http://www.cnblogs.com/zhangqigao/articles/8990400.html