2010-02-12 68 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