2010-02-12 32 views
33

me gustaría utilizar simplejson para serializar un modelo de Django. El serializador de Django no admite diccionarios ... y simplejson no es compatible con Django Querysets. Esto es todo un acertijo.JSON Serializar Django modelos con simplejson

En el modelo hay patrocinadores que tienen una clave externa para patrocinar nivel, estoy tratando de agrupar todos los patrocinadores que pertenecen a un cierto nivel patrocinador juntos. Aquí está el código que genera la lista:

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] 

Esto es lo sponsor_dict parece una vez que se "hizo"

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

Sólo he añadido un patrocinador en cada nivel, a excepción de bronce, sólo para mostrar cómo se trabajos. Todo lo que quiero hacer es ponerlo "todo" en JSON para que jQuery pueda interpretarlo fácilmente. ¿Pueden los otros serializadores de Django (como XML o YAML) lograr esto? ¿Puedo "extender" el Serializador JSON de Django para manejar diccionarios o "extender" simplejson para manejar objetos Django QuerySet?

Respuesta

39

Me gustaría ir con extender simplejson. Básicamente, desea conectar la serialización de django cuando el codificador JSON encuentra un QuerySet. Se podría utilizar algo como:

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) 

Para obtener más información sobre el método de default, echar un vistazo a simplejson documentation. Ponlo en un módulo de Python, luego importa dumps y listo. Pero tenga en cuenta que esta función solo lo ayudará a serializar las instancias QuerySet, no a las instancias Model directamente.

+1

esto es muy inteligente – babonk

10

basado en la respuesta de Clemente, que lo hacían para tener modelos en JSON también.

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

Si usted tiene una pregunta que tiene que hacer clic en el botón 'haga la pregunta' en la parte parte superior derecha. El formulario 'Su respuesta' se usa para publicar respuestas. – Pickels

+13

Mis disculpas. Solo intenté complementar el tema, ya que la respuesta principal destaca su incapacidad para serializar objetos. Este objetivo se logra, ya que el código funciona. Mi pregunta acerca de que sea una buena idea o una mala estaba destinado a invitar a la discusión acerca de una mejor integración, y ciertamente no desprecio de nadie – jcage

13

Una forma muy flexible para serializar la mayoría de las estructuras de Django es usar la clase serializador encontró here

+1

Sólo se aplicó esto. ¡Es brillante! Este script merece más reconocimiento. – Glycerine

+1

+1 - Esto también funcionó muy bien para mí. – RyanBrady

+0

Esta es una solución muy simple y adaptable. – stormlifter

Cuestiones relacionadas