Django里面,当我们使用post提交form的时候,如果出现了错误,我们可以直接把错误通过obj传回给前端。如果当我们使用Ajax方式和自定义的form提交数据,这个时候就需要在后端把错误信息序列化,然后传回前端进行反序列化了。


对于错误信息,django提供了几种转换的方式。


第一种是as_json,他可以把整个错误信息转换为字符串的格式,这样子我们可以直接序列化json.dumps传到前端去。他的问题在于这个错误信息是一个嵌套的字典,意味着在前端需要反序列化2次才能获取正确的信息。


view.py

from django import formsfrom django.forms import widgets, fields
class LoginForm(forms.Form):
    username = fields.CharField()
    password = fields.CharField(
        max_length=64,
        min_length=12
    )
def login(request):
    import json
    res = {'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.cleand_data)        
        else:            
        # print(obj.errors, type(obj.errors))
            res['error'] = obj.errors.as_json()  # 转为json格式
            return HttpResponse(json.dumps(res))


login.html

<body>
    <form id="fm">
        {% csrf_token %}        
        <p><input type="text" name="username" /></p>
        <p><input type="password" name="password" /></p>
        <a id="submit">ajax提交</a>
    </form>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        // 页面框架加载完自动执行
        $('#submit').click(function(){
            $.ajax({
                url:'/login.html',
                type:'POST',
                data:$('#fm').serialize(),
                success:function(arg){
                    console.log(arg);
                    arg = JSON.parse(arg);  // 转为字典
                    console.log(arg);
                },
                error: function(){

                }
            })
        })    
    </script>
 </body>



一种优化的方法是自定义一个Json的报错格式,通过判断isinstance(filed, XXX) 里面 XXX的类型,我们手动执行不同的操作

from django import forms
from django.forms import widgets, fields
class LoginForm(forms.Form):
    username = fields.CharField()
    password = fields.CharField(
        max_length=64,
        min_length=12
    )

# 序列化,转换为指定数据类型
import json
from django.core.exceptions import ValidationError

class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field, ValidationError):
            return {'code':field.code, 'messages': field.messages}
        else:
            return json.JSONEncoder.default(self, field)

def login(request):
    res = {'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.cleand_data)
        else:
            # print(obj.errors, type(obj.errors))
            # res['error'] = obj.errors.as_json()  # 转为json格式
            print(type(obj.errors.as_data()))
            for k,v in obj.errors.as_data().items():
                print(k,v)  # 这里v是ValidationError类型,不能序列化
            res['error'] = obj.errors.as_data()
        result = json.dumps(res, cls=JsonCustomEncoder)
        return HttpResponse(json.dumps(result))


类似的,当我们操作时间数据的时候,默认他没法序列化,我们可以通过类似的方法进行转换

import json 
from datetime import date 
from datetime import datetime 
class JsonCustomEncoder(json.JSONEncoder): 
    def default(self, field): 
        if isinstance(field, datetime): 
            return o.strftime('%Y-%m-%d %H:%M:%S') 
        elif isinstance(field, date): 
            return o.strftime('%Y-%m-%d')   # 转成字符串类型
        else: 
            return json.JSONEncoder.default(self, field) 
v = {'k':'123', "k1":datetime.datetime.now()}   
ds = json.dumps(v, cls=JsonCustomEncoder)


最后看看其他类型的序列化

对QuerySet的序列化

from django.core import serializers
v = models.tb.objects.all()
data = serializers.serialize("json", v)


对QuerySet value结构的序列化

import json
from datetime import date
from datetime import datetime
class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field, datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(field, date):
            return field.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, field)
v = models.tb.objects.values('id','name','ctime')
v = list(v)  # 把(类似列表的queryset类型)转换为列表
v = json.dumps(v,cls=JsonCustomEncoder)  # 这里cls只对ctime操作。
# 如果没有ctime这个类型,只写上边的三句就可以实现


以上资料出自老男孩的培训视频~