2010-09-20 17 views
34

Ho lavorato allo sviluppo di alcuni servizi RESTful in Django da utilizzare con le app Flash e Android.Serializzazione di oggetti chiave esterna in Django

Lo sviluppo dell'interfaccia dei servizi è stato piuttosto semplice, ma ho riscontrato un problema con la serializzazione di oggetti che hanno una chiave esterna e molte e molte relazioni.

Ho un modello come questo:

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) 

Poi vorrei eseguire una query su questo modello come questo, utilizzando select_related(), per essere sicuri che le relazioni di chiave esterna sono seguiti:

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

Una volta che ho l'oggetto, ho serializzare, e passare che torna a mio punto di vista:

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

Questo è quello che torno, si noti che le chiavi esterne (object_type e individuali) sono solo le id per i relativi oggetti correlati.

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

Questo è grande, ma quello che speravo per quando si utilizza select_related() era che sarebbe compilare automaticamente i campi chiave esterna con il relativo oggetto, id non solo dell'oggetto.

Sono recente convertito in Django, ma ho impiegato molto tempo a sviluppare con CakePHP.

Quello che mi piace davvero del Cake ORM era che avrebbe seguito le relazioni e creato oggetti nidificati per impostazione predefinita, con la possibilità di separare le relazioni quando stavi chiamando la tua query.

Ciò ha reso molto semplice l'astrazione dei servizi in un modo che non richiedeva alcun intervento caso per caso.

Vedo che Django non lo fa di default, ma c'è un modo per serializzare automaticamente un oggetto e tutti gli oggetti correlati? Qualsiasi consiglio o lettura sarebbe molto apprezzato.

+1

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

risposta

24

Avevo un requisito simile anche se non per scopi RESTful. Sono stato in grado di ottenere ciò di cui avevo bisogno utilizzando un modulo di serializzazione "completo", nel mio caso Django Full Serializers. Questo fa parte di wadofstuff ed è distribuito con la nuova licenza BSD.

Wadofstuff rende abbastanza semplice. Ad es. nel tuo caso dovresti fare quanto segue:

Prima di tutto, installa wadofstuff.

In secondo luogo, aggiungere la seguente impostazione al file settings.py:

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

In terzo luogo, fare una piccola modifica al codice utilizzato per la serializzazione:

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

Il cambiamento principale è il parametro relations parola chiave . L'unico (minimo) trucco consiste nell'usare il nome dei campi che formano la relazione e non i nomi dei relativi modelli.

Caveat

Dal documentation:

il rotolo di roba serializzatori sono compatibili al 100% con i serializzatori Django durante la serializzazione un modello. Durante la deserializzazione di un flusso di dati, la classe Deserializer attualmente funziona solo con dati serializzati restituiti dai serializzatori standard Django.

(enfasi aggiunta)

Spero che questo aiuti.

10

UPDATE: In realtà la soluzione di Manoj è un po 'obsolete, Wad di serializzatore Stuff ha stato lasciato non aggiornato per qualche tempo e quando l'ho provato, sembra che non supporti più Django 1.6.

Tuttavia, dare un'occhiata a Django's official doc here. Fornisce in qualche modo l'uso della chiave naturale integrata. Sembra che il serializzatore integrato di django abbia un piccolo problema nel supportare l'uso di ImageField come parte della chiave naturale. Ma ciò può essere facilmente risolto da te stesso.

+0

Grazie! Ho dimenticato la chiave naturale;) –

+0

@Quando Haochen, il tuo collegamento sembra non essere più raggiungibile. Ma sono d'accordo con te sul fatto che la soluzione sopra indicata sia obsoleta. Potresti aggiornare il link? –

Problemi correlati