Django model,QuerySet 序列化成json的方法

转载 2013年12月05日 14:10:11

转自:http://www.yihaomen.com/article/python/279.htm


提到序列化与反序列化,通常会想到 json ,xml .在J2EE的开发中,这是很常用的技术,比如一个java class与xml之间的序列化与反序列化,我们可以通过 xstream来实现,如果是与json之间的转换,我们可以通过 gson.jar或者jsonlib.jar 来实现。方法很多,也是常见的方法。

但在python 中,我们常用的是json 的序列化,python2.7 已经包含了json package,这个也是从simplejson 基础上改变而来。这个json 包主要提供了dump,load 来实现dict 与 字符串之间的序列化与反序列化,这很方便的可以完成,可以参考这篇文章python json。但现在的问题是,这个json包不能序列化 django 的models 里面的对象的实例。
经过分析,网络搜索,发现有如下解决方案.

利用 from django.core import serializers 的方法实现

程序代码 程序代码

from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all())
data1 = serializers.serialize("json", SomeModel.objects.filter(myfield1=myvalue))

上面两个是没有问题的,因为序列化的对象是 Queryset, 因此是成功的。但如果是用SomeModel.objects.get(id=myid) 得到一个具体的实例的时候,问题就来了
程序代码 程序代码

data = serializers.serialize("json", SomeModel.objects.get(id=myid))

肯定会出现如下错误:
for obj in queryset:
TypeError: 'SomeModel' object is not iterable
一看错误就知道,因为  SomeModel.objects.get(id=myid) 返回的是一个具体的实例,而不是一个集合对象,因此是不可以 iterable 的。所以报错。

从上面的分析可以看出  django的 serializers 只支持 queryset,而不支持model的实例,那么怎么实现呢?
1.我们自己把这个单个对象模拟成一个集合,然后去掉前后的"[""]"符号,就可以了。

程序代码 程序代码

from django.utils import simplejson
from django.db import models
from django.core.serializers import serialize,deserialize
from django.db.models.query import QuerySet
from django.test import TestCase

class MyEncoder(simplejson.JSONEncoder):
     """ 继承自simplejson的编码基类,用于处理复杂类型的编码
     """
     def default(self,obj):
             if isinstance(obj,QuerySet):
                 """ Queryset实例
                 直接使用Django内置的序列化工具进行序列化
                 但是如果直接返回serialize('json',obj)
                 则在simplejson序列化时会被从当成字符串处理
                 则会多出前后的双引号
                 因此这里先获得序列化后的对象
                 然后再用simplejson反序列化一次
                 得到一个标准的字典(dict)对象
                 """
                 return simplejson.loads(serialize('json',obj))
             if isinstance(obj,models.Model):
                 """
                 如果传入的是单个对象,区别于QuerySet的就是
                 Django不支持序列化单个对象
                 因此,首先用单个对象来构造一个只有一个对象的数组
                 这是就可以看做是QuerySet对象
                 然后此时再用Django来进行序列化
                 就如同处理QuerySet一样
                 但是由于序列化QuerySet会被'[]'所包围
                 因此使用string[1:-1]来去除
                 由于序列化QuerySet而带入的'[]'
                 """
                 return simplejson.loads(serialize('json',[obj])[1:-1])
             if hasattr(obj, 'isoformat'):
                 #处理日期类型
                 return obj.isoformat()
             return simplejson.JSONEncoder.default(self,obj)

def jsonBack(json):
     """    进行Json字符串的反序列化
         一般来说,从网络得回的POST(或者GET)
         参数中所包含json数据
         例如,用POST传过来的参数中有一个key value键值对为
         request.POST['update']
         = "[{pk:1,name:'changename'},{pk:2,name:'changename2'}]"
         要将这个value进行反序列化
         则可以使用Django内置的序列化与反序列化
         但是问题在于
         传回的有可能是代表单个对象的json字符串
         如:
         request.POST['update'] = "{pk:1,name:'changename'}"
         这是,由于Django无法处理单个对象
         因此要做适当的处理
         将其模拟成一个数组,也就是用'[]'进行包围
         再进行反序列化
     """
     if json[0] == '[':
         return deserialize('json',json)
     else:
         return deserialize('json','[' + json +']')

def getJson(**args):
     """    使用MyEncoder这个自定义的规则类来序列化对象
     """
     result = dict(args)
     return simplejson.dumps(result,cls=MyEncoder)

在上面的例子中,自定义了一个序列化规则类MyEncoder,用来处理集合或者集合对象,然后实现了一个可变参数的工具方法getJson,用于传入多个参数,并将其一同序列化。另外还有一个反序列化对象的方法jsonBack,接受一个代表对象或者对象集合的json而返回一个对象集合。这样一来就可以很好的使用配合SimpleJson和Django来完成序列化工作了

2.直接利用python 2.7 提供的json包,或者用simplejson都可以
首先,你需要在django model的定义中增加一个方法toJSON,利用了django model  能访问 _meta.fields 得到相关属性而得到,例子如下

程序代码 程序代码

class Category(models.Model):
    autoid = models.AutoField(primary_key=True)
    email=models.CharField(max_length=150,blank=False)
    comtype=models.CharField(max_length=20,blank=False)
    catname=models.CharField(max_length=150,blank=False)  
    
    def __unicode__(self):
        return '%s' % (self.catname)
    
    def toJSON(self):
        import json
        return json.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

现在用django查出数据,并转换成json
程序代码 程序代码

row=models.Category.objects.get(autoid=23)    
print row.toJSON()

你会发现,成功转换了。当然,这个toJSON方法,如果要求可读性比较好的话,可以这样写
程序代码 程序代码

def toJSON(self):
        fields = []
        for field in self._meta.fields:
            fields.append(field.name)
    
        d = {}
        for attr in fields:
            if isinstance(getattr(self, attr),datetime.datetime):
                d[attr] = getattr(self, attr).strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(getattr(self, attr),datetime.date):
                d[attr] = getattr(self, attr).strftime('%Y-%m-%d')
            else:
                d[attr] = getattr(self, attr)
    
        import json
        return json.dumps(d)


【已解决】Object of type 'QuerySet' is not JSON serializable

报错图片 报错的意思: QuerySet的数据格式不是JSON支持的序列化格式 我的代码: def ajax_value(request): ajax_testvalue = ...
  • teavamc
  • teavamc
  • 2017年09月01日 20:49
  • 2006

XXX is not JSON serializable 另类解决方式

这个问题在网上看了很多方法,根绝和我的错误对不上,没办法只好不停找寻,最终发现了一个合适的方式,其中原因我也说不清,也许其他人也会遇到,放出来让大家瞧瞧吧 我之所以会遇到这个问题我认为不是代码问题。我...
  • qq_20373723
  • qq_20373723
  • 2017年04月03日 15:53
  • 2729

Django笔记---项目报错之“xxx is not JSON serializable”

1. 错误说明:    在 Django 项目中,我们会用到 Session,比如:购物车项目中,就会用 Session 来保存一个商品对象。但是,当我们的 Django 版本高于等于 1.6 时(本...
  • GuLu_GuLu_jp
  • GuLu_GuLu_jp
  • 2015年06月08日 18:16
  • 3291

datetimeTypeError: datetime.datetime(2015, 1, 29, 8, 17, 41) is not JSON serializable

解决json.dumps不能序列化datetime类型的问题 by Ajia - Mar 20th, 2014 - posted in python | Comments 使用python自带...
  • design321
  • design321
  • 2015年01月30日 16:26
  • 4615

[Python]json 错误xx is not JSON serializable

在使用json的时候经常会遇到xxx is not JSON serializable,也就是无法序列化某些对象。 经常使用django的同学知道django里面有个自带的Encoder来序列化时间...
  • lzz957748332
  • lzz957748332
  • 2014年03月16日 14:06
  • 27652

ValuesQuerySet对象 转换成json

def search(request): kw = request.GET.get('kw') print kw word = Cnword.objects.filter(wo...
  • qq_24861509
  • qq_24861509
  • 2015年10月16日 06:07
  • 3223

django中将models以json形式返回

一开始这么写的
  • magic_wz
  • magic_wz
  • 2014年10月23日 17:22
  • 2918

Django ValuesQuerySet转json

在使用ValuesQuerySet存放查询结果时,有时需要转为json,但并不能直接使用json.dumps()直接转,而是需要经过下面一个步骤:result_set = Apple.objects....
  • lanyang123456
  • lanyang123456
  • 2017年05月30日 11:14
  • 1690

django 将model转换成想要都json格式

model: class SysRole(models.Model): id = models.CharField(db_column='ID', primary_key=True, max_...
  • wjy397
  • wjy397
  • 2015年11月02日 20:18
  • 1969

为Django中的模型Model添加JSON类型字段

Django里面让,Model用于JSON字段,添加一个JSONField自动类型如下: class JSONField(models.TextField): __metaclass__ =...
  • trbbadboy
  • trbbadboy
  • 2014年07月24日 17:00
  • 4411
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Django model,QuerySet 序列化成json的方法
举报原因:
原因补充:

(最多只允许输入30个字)