Django 里对 queryset 和 model 的序列化真的是一个老生常谈的问题。对于 queryset,我们一般用 django 内置的 serialize,但是它有一个缺点,就是不能对 model 实例进行序列化。这时候就需要我们手动进行调整。
一、思路。
我们需要自定义一个序列化函数,但是这个函数不能只单单满足 querySet 或者 model,我们应该把它变成一个更加通用的方法。这里我们直接用到了 json 类,这是最基本的序列化类,它支持自定义序列化规则,我们可以根据序列化对象的不同来应用不同的规则。
二、实现
# coding=utf-8
import json
from django.db import models
from django.core.serializers import serialize
from django.db.models.query import QuerySet
class JSONEncoder(json.JSONEncoder):
""" 继承自simplejson的编码基类,用于处理复杂类型的编码
"""
def default(self, obj):
if isinstance(obj, QuerySet):
""" Queryset实例
直接使用Django内置的序列化工具进行序列化
但是如果直接返回serialize('json',obj)
则在simplejson序列化时会被从当成字符串处理
则会多出前后的双引号
因此这里先获得序列化后的对象
然后再用simplejson反序列化一次
得到一个标准的字典(dict)对象
"""
return json.loads(serialize('json', obj))
if isinstance(obj, models.Model):
"""
如果传入的是单个对象,区别于QuerySet的就是
Django不支持序列化单个对象
因此,首先用单个对象来构造一个只有一个对象的数组
这是就可以看做是QuerySet对象
然后此时再用Django来进行序列化
就如同处理QuerySet一样
但是由于序列化QuerySet会被'[]'所包围
因此使用string[1:-1]来去除
由于序列化QuerySet而带入的'[]'
"""
return json.loads(serialize('json', [obj])[1:-1])
if hasattr(obj, 'isoformat'):
# 处理日期类型
return obj.isoformat()
return json.JSONEncoder.default(self, obj)
使用方法:
json.dumps(result, cls=JSONEncoder)