2010-09-20 20 views
34

He estado trabajando en el desarrollo de algunos servicios RESTful en Django para ser utilizado con aplicaciones Flash y Android.Serialización de objetos clave extranjeros en Django

El desarrollo de la interfaz de servicios ha sido bastante simple, pero he tenido un problema con la serialización de objetos que tienen clave externa y muchas relaciones.

Tengo un modelo como este:

class Artifact(models.Model): 
    name    = models.CharField(max_length = 255) 
    year_of_origin  = models.IntegerField(max_length = 4, blank = True, null = True) 
    object_type   = models.ForeignKey(ObjectType, blank = True, null = True) 
    individual   = models.ForeignKey(Individual, blank = True, null = True) 
    notes    = models.TextField(blank = True, null = True) 

entonces yo realizar una consulta sobre este modelo como este, usando select_related(), para asegurarse de que las relaciones de clave externa se siguen:

artifact = Artifact.objects.select_related().get(pk=pk) 

Una vez que tengo el objeto, lo serializo, y lo transfiero a mi vista:

serializers.serialize("json", [ artifact ]) 

Esto es lo que recibo, tenga en cuenta que las claves foráneas (object_type e individual) son solo las identificaciones de sus objetos relacionados.

[ 
     { 
      pk: 1 
      model: "artifacts.artifact" 
      fields: { 
       year_of_origin: 2010 
       name: "Dummy Title" 
       notes: "" 
       object_type: 1 
       individual: 1 
      } 
     } 
] 

Esto es muy bueno, pero lo que yo esperaba cuando se utiliza select_related() fue que sería automáticamente los campos de clave externa con el objeto relacionado, no sólo el ID de objeto.

Soy un reciente converso a Django, pero dedico bastante tiempo a desarrollar con CakePHP.

Lo que realmente me gusta de Cake ORM es que seguiría las relaciones y crearía objetos anidados por defecto, con la capacidad de desvincular las relaciones cuando estaba llamando a su consulta.

Esto hizo que fuera muy fácil abstraer los servicios de una manera que no requiriera ninguna intervención caso por caso.

Veo que Django no hace esto por defecto, pero ¿hay alguna forma de serializar automáticamente un objeto y todos sus objetos relacionados? Cualquier consejo o lectura sería muy apreciado.

+1

[PEP-008] (http://www.python.org/dev/peps/pep-0008) –

Respuesta

24

Tenía un requisito similar aunque no para fines RESTful. Logré lo que necesitaba utilizando un módulo de serialización "completo", en mi caso Django Full Serializers. Esto es parte de wadofstuff y se distribuye bajo la nueva licencia BSD.

Wadofstuff hace que esto sea bastante fácil. Por ej. en su caso, tendría que hacer lo siguiente:

Primero, instale wadofstuff.

En segundo lugar, agregue la siguiente configuración en el archivo de settings.py:

SERIALIZATION_MODULES = { 
    'json': 'wadofstuff.django.serializers.json' 
} 

En tercer lugar, hacer un pequeño cambio en el código utilizado para la serialización:

artifact = Artifact.objects.select_related().get(pk=pk) 
serializers.serialize("json", [ artifact ], indent = 4, 
    relations = ('object_type', 'individual',)) 

El cambio fundamental es el parámetro relations palabra clave . El único (menor) problema es usar el nombre de los campos que forman la relación, no los nombres de los modelos relacionados.

Caveat

Desde el documentation:

el fajo de materia serializadores son 100% compatible con los serializadores Django al serializar un modelo. al deserializar un flujo de datos de la clase del Deserializer actualmente sólo funciona con datos serializados devueltos por los serializadores Django estándar.

(Énfasis añadido)

Espero que esto ayude.

10

ACTUALIZACIÓN: En realidad la solución de Manoj está un poco anticuado, el taco de serializador de la materia tiene ha quedado sin actualizar durante un tiempo y cuando lo intenté, parece que ya no es compatible con Django 1.6.

Sin embargo, echar un vistazo a Django's official doc here. Proporciona una forma de evitar el uso de la clave natural incorporada. Parece que el serializador incorporado de django tiene un pequeño problema al admitir el uso de ImageField como parte de la clave natural. Pero eso puede ser arreglado fácilmente por usted mismo.

+0

Gracias! Me olvidé de la clave natural;) –

+0

@Shen Haochen, su enlace parece no ser alcanzable más. Pero estoy de acuerdo con usted en que la solución antes mencionada está desactualizada. ¿Podrías refrescar el enlace? –

Cuestiones relacionadas