2010-09-20 9 views
34

J'ai travaillé sur le développement de certains services RESTful dans Django pour les utiliser avec des applications Flash et Android.Sérialisation d'objets de clé étrangère dans Django

Développer l'interface de services a été assez simple, mais j'ai rencontré un problème avec la sérialisation des objets qui ont une clé étrangère et de nombreuses relations.

J'ai un modèle comme celui-ci:

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) 

alors j'effectuer une requête sur ce modèle comme celui-ci, en utilisant select_related(), pour être sûr que les relations clés étrangères sont suivies:

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

Une fois que j'ai l'objet, je le sérialise, et le renvoie à ma vue:

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

Voici ce que je reçois, notez que les clés étrangères (object_type et individual) ne sont que les identifiants de leurs objets associés.

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

Cela tombe bien, mais ce que j'espérais lors de l'utilisation select_related() était qu'il remplit automatiquement les champs de clé étrangère avec l'objet associé, non seulement l'id de l'objet.

Je suis récemment converti en Django, mais j'ai passé pas mal de temps à développer avec CakePHP. Ce que j'aime vraiment dans le Cake ORM était qu'il suivrait les relations et créerait des objets imbriqués par défaut, avec la possibilité de délier les relations quand vous appeliez votre requête. Cela a rendu très facile l'abstraction des services d'une manière qui ne nécessitait aucune intervention au cas par cas.

Je vois que Django ne le fait pas par défaut, mais existe-t-il un moyen de sérialiser automatiquement un objet et tous ses objets associés? Tous les conseils ou la lecture seraient très appréciés.

+1

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

Répondre

24

J'avais une exigence similaire, mais pas à des fins RESTful. J'ai été capable de réaliser ce dont j'avais besoin en utilisant un module de sérialisation "complet", dans mon cas Django Full Serializers. Ceci fait partie de wadofstuff et est distribué sous la nouvelle licence BSD.

Wadofstuff rend cela assez facile. Par exemple Dans votre cas, vous devez effectuer les opérations suivantes:

D'abord, installez wadofstuff.

En second lieu, ajoutez le paramètre suivant à votre fichier settings.py:

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

Troisièmement, faire une légère modification du code utilisé pour la sérialisation:

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

Le principal changement est le paramètre de mot-clé relations . Le seul (mineur) gotcha est d'utiliser le nom des champs formant la relation et non les noms des modèles associés.

caveat

De l'documentation:

Le Wad de Stuff serializers sont 100% compatibles avec les Django serializers lors de la sérialisation un modèle. Lors de la désérialisation d'un flux de données, la classe Deserializer ne fonctionne actuellement qu'avec les données sérialisées renvoyées par les sérialiseurs Django standard.

(souligné dans l'original)

Hope this helps.

10

MISE À JOUR: En fait, la solution de Manoj est un peu vieillot, Wad de sérialiseur Stuff a été laissé non-mis à jour depuis un certain temps et quand j'ai essayé, il semble qu'il ne supporte plus Django 1.6. Cependant, regardez Django's official doc here. Il fournit un moyen d'utiliser la clé naturelle intégrée. Il semble que le sérialiseur intégré de django a un petit problème en supportant ImageField dans le cadre de la clé naturelle. Mais cela peut être facilement fixé par vous-même.

+0

Merci! J'ai oublié de clé naturelle;) –

+0

@Shen Haochen, votre lien semble ne plus être joignable. Mais je suis d'accord avec vous que la solution mentionnée ci-dessus est obsolète. Pourriez-vous s'il vous plaît rafraîchir le lien? –

Questions connexes