2010-02-12 16 views
33

Ich möchte mit Simplejson ein Django-Modell serialisieren. Djangos Serializer unterstützt keine Wörterbücher ... und Simplejson unterstützt keine Django-Querysets. Das ist ein ziemliches Rätsel.JSON Serialisierung von Django-Modellen mit simplejson

Im Modell gibt es Sponsoren, die einen Fremdschlüssel zum Sponsorenlevel haben, ich versuche alle Sponsoren, die zu einem bestimmten Sponsorniveau gehören, zusammen zu gruppieren. Hier ist der Code, der die Liste erzeugt:

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] 

Hier ist, was sponsor_dict aussieht, wenn es

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

Ich habe nur einen Sponsor in jeder Ebene, mit Ausnahme von Bronze, nur um zu zeigen, wie es funktioniert. Alles, was ich tun möchte, ist "alles" in JSON zu bekommen, damit jQuery es leicht interpretieren kann. Können Djangos andere Serialisierer (wie XML oder YAML) dies erreichen? Kann ich den JSON-Serializer von Django "erweitern", um Wörterbücher zu behandeln, oder "erweitere" simplejson, um Django-QuerySet-Objekte zu behandeln?

Antwort

39

Ich würde mit der Erweiterung simplejson gehen. Grundsätzlich möchten Sie die Serialisierung von Django einbinden, wenn der JSON-Encoder auf ein QuerySet stößt.

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) 

Für weitere Informationen über default Methode, einen Blick auf simplejson documentation: Sie könnte so etwas wie verwenden. Setzen Sie das in ein Python-Modul, dann importieren Sie dumps und Sie sind gut zu gehen. Beachten Sie jedoch, dass diese Funktion nur dazu dient, QuerySet Instanzen zu initialisieren, nicht Model Instanzen direkt.

+1

zu verwenden, um dies sehr klug ist – babonk

10

basierend auf Clements Antwort, habe ich das getan, um Modelle in JSON zu bekommen.

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

Wenn Sie eine Frage haben, müssen Sie die ‚Frage stellen‘ Button auf der klicken oben rechts. Das Formular 'Ihre Antwort' wird verwendet, um Antworten zu posten. – Pickels

+13

Entschuldigung. Ich wollte nur das Thema ergänzen, da die Hauptantwort darauf hinweist, dass Objekte nicht serialisiert werden können. Dieses Ziel ist erreicht, da der Code funktioniert. Meine Frage, ob es eine gute oder eine schlechte Idee ist, sollte eine Diskussion über bessere Integration einleiten, und sicherlich nicht jedermanns Verachtung. – jcage

13

Eine wirklich flexible Art und Weise die meisten Strukturen in django zu serialisiert ist die Serializer Klasse here gefunden

+1

Es ist brilliant! Dieses Skript verdient mehr Anerkennung. – Glycerine

+1

+1 - Das hat auch für mich sehr gut funktioniert. – RyanBrady

+0

Dies ist eine sehr einfache und anpassungsfähige Lösung. – stormlifter

Verwandte Themen