Django的序列化

在开发TMS的过程中,后期经常采用一个页面由几个url的数据共同构成的情况,比如,Root提供显示面板,table1提供面板中某个Table表格的数据来源,chart1提供面板中某个图表的数据来源。而在Root的html模板中,使用ajax发送访问table1和chart1的请求,并获取返回的Json数据。

是的。ajax通常得到的是JsonResponse格式的返回数据,因此,我们需要想办法将Django查询的QuerySet转换成Json格式输出,即,序列化。

一、目前我使用的方法

QuerySet的序列化

先使用values将所需字段弄成QuerySet中类似Dict的存在,然后转换成list

@ajax_required
def testcaseDeps(request):
    """按部门统计某年内的各部分更新、修改的用例数"""
    year = request.GET.get('year')
    qs = swtTestCase.objects.filter(createDate__year=year).values('team').\
        annotate(adds=swtTestCase.ADD, dels=swtTestCase.DEL, mods=swtTestCase.MOD, news=swtTestCase.NEW)
    return JsonResponse(dict(datas=list(qs)))

RawQuerySet的序列化

RawQuerySet如果不带其他表格的字段,可通过Django提供的serializers来序列化(其实对于上面QuerySet也一样)。但是如果查询的时候带别的Table的字段,比如,使用left join后的查询结果,那么使用该方法序列化后不带额外需要的字段,需要自己写方法进行处理。

from django.core import serializers
query = 'select * from users_user'
data = serializers.serialize('json', User.objects.raw(query))
query = "SELECT users_user.displayName, users_remindjira.* from users_user left join users_remindjira on users_user.username=users_remindjira.`user` where users_remindjira.day = '{}' and users_user.dep_id='{}'".format(t, depId)
qs = RemindJira.objects.raw(query)
def rawList(qsIn):
    """将查表得到的RawQuerySet转换成[{},{}]格式,方便用于后面的转换成Json格式的输出"""
    myout = []
    for item in qsIn:
        tt = item.__dict__
        tt.pop('_state')
        tt.pop('id')
        myout.append(tt)
    return myout
return JsonResponse(dict(datas=rawList(qs)))

二、Django自带的模型转字典方法

Django自带的模型转字典的方法是model_to_dict,使用它的话,一是只针对单个对象,需要对QuerySet中的所有元素逐个进行处理;二是图片、文件之类的字段无法转换。

from django.forms.models import model_to_dict
queryset = Publisher.objects.all()
data = []
for i in queryset:
	data.append(model_to_dict(i))
import json
    return HttpResponse(json.dumps(data), content_type='application/json')

三、serializers

上面讲处理RawQuerySet的时候已经提过一次了。但是它给出的json字段格式与我们期望的稍有不同

from django.core import serializers
qs = User.objects.all()
rzt = serializers.serialize('json', qs)
return HttpResponse(rzt)

它出来的结果如下:

>>>print(json.loads(rzt)[0])
{'model': 'users.user',
 'pk': 53,
 'fields': {
     'password': 	'pbkdf2_sha256$150000$nCgM7okk79UN$kGIjI8hyzBGzyZe1cfpJRMP+Plm6GGpSXRzIxg9xgTM=',
  	 'last_login': None,
     'is_superuser': False,
     'username': 'biwenqing',
     'first_name': '',
     'last_name': '',
     'email': 'biwenqing@hisense.com',
     'is_staff': False,
     'is_active': False,
     'date_joined': '2020-04-22T13:04:44.617Z',
     'dep': '手机专项测试室',
     'displayName': '毕文青',
     'mobile': None,
     'employeeNumber': None,
     'telephone': None,
     'groups': [5],
     'user_permissions': []}
}

可以看到,它额外加了一些东西(pk,model),而我们实际需要的都在fields中。

四、Django的rest_framework

JSON格式

对象 {键:值, }
数组 [值 , 值 ]

对象中的值可以为数组;数组中值可以为对象