2010-02-12 55 views
33

我想使用simplejson序列化Django模型。 Django的序列化程序不支持字典...并且simplejson不支持Django Querysets。这是一个相当难解的问题。JSON使用simplejson序列化Django模型

在模型中有赞助商有一个外键赞助级别,我试图将属于某个赞助商级别的所有赞助者组织在一起。下面是生成列表的代码:

from django.shortcuts import get_list_or_404 
from special_event.models import Sponsor, SponsorLevel 

sponsor_dict = {} 

roadie_sponsors = get_list_or_404(Sponsor, level__category = SponsorLevel.ROADIE_CHOICE) 

for item in roadie_sponsors: 
    try: 
     sponsor_dict[item.level.name].append(item) 
    except KeyError: 
     sponsor_dict[item.level.name] = [item] 

这里的sponsor_dict的样子,一旦它的“制造”

{ 
    'Fan': [<Sponsor: Fan Sponsor>], 
    'VIP': [<Sponsor: VIP Sponsor>], 
    'Groupie': [<Sponsor: Groupie Sponsor>], 
    'Silver': [<Sponsor: Silver Sponsor>], 
    'Bronze': [<Sponsor: Another Bronze Sponsor>, <Sponsor: Bronze Sponsor>] 
} 

我只在每个级别增加了一个赞助商,除了青铜,只是为了显示它是如何作品。我想要做的就是将它“全部”放入JSON中,以便jQuery可以轻松解释它。 Django的其他序列化程序(如XML或YAML)可以完成此任务吗?我可以“扩展”Django JSON序列化程序来处理字典或“扩展”simplejson来处理Django QuerySet对象吗?

回答

39

我会去扩展simplejson。基本上,你想在JSON编码器遇到QuerySet时插入django的序列化。你可以使用类似:

from json import dumps, loads, JSONEncoder 

from django.core.serializers import serialize 
from django.db.models.query import QuerySet 
from django.utils.functional import curry 

class DjangoJSONEncoder(JSONEncoder): 
    def default(self, obj): 
     if isinstance(obj, QuerySet): 
      # `default` must return a python serializable 
      # structure, the easiest way is to load the JSON 
      # string produced by `serialize` and return it 
      return loads(serialize('json', obj)) 
     return JSONEncoder.default(self,obj) 

# partial function, we can now use dumps(my_dict) instead 
# of dumps(my_dict, cls=DjangoJSONEncoder) 
dumps = curry(dumps, cls=DjangoJSONEncoder) 

欲了解更多信息上default方法,看看simplejson documentation。把它放在一个python模块中,然后导入dumps,你很好。但请注意,此功能只会帮助您直接序列化QuerySet实例,而不是Model实例。

+1

这是非常聪明的 – babonk 2012-03-08 19:29:30

10

基于克莱门特的回答,我做到了这一点,以获得模型到JSON以及。

def toJSON(obj): 
    if isinstance(obj, QuerySet): 
     return simplejson.dumps(obj, cls=DjangoJSONEncoder) 
    if isinstance(obj, models.Model): 
     #do the same as above by making it a queryset first 
     set_obj = [obj] 
     set_str = simplejson.dumps(simplejson.loads(serialize('json', set_obj))) 
     #eliminate brackets in the beginning and the end 
     str_obj = set_str[1:len(set_str)-2] 
    return str_obj 
+0

如果你有你需要点击“问问题”按钮问题右上。 '您的答案'表单用于发布答案。 – Pickels 2010-08-14 20:41:37

+13

我的歉意。我只是打算赞扬这个话题,因为主要答案表明它无法序列化对象。这个目标已经完成,因为代码确实有效。 我的问题是它是一个好主意还是坏主意,是为了邀请关于更好整合的讨论,当然不是任何人的鄙视 – jcage 2010-08-14 21:01:33

13

一个序列化Django的大多数结构真正灵活的方式是使用串行类中here

+1

刚刚实现了这一点。这个棒极了!这个剧本值得更多的认可。 – Glycerine 2011-10-13 13:57:20

+1

+1 - 这对我来说也很好。 – RyanBrady 2011-11-01 23:49:12

+0

这是一个非常简单和适应性强的解决方案。 – stormlifter 2012-03-02 19:16:35