2013-01-21 32 views
11

ProblemaDjango REST quadro e rapporti generici

Ho un modello con i seguenti generici campi chiave esterna standard:

content_type = models.ForeignKey(ContentType) 
object_id = models.PositiveIntegerField() 
event_object = generic.GenericForeignKey('content_type', 'object_id') 

Secondo la documentazione del framework REST, posso effettuare le seguenti operazioni a puntate questo correttamente:

class WhateverSerializer(serializers.ModelSerializer): 
    event_object = serializers.RelatedField(source='event_object') 

Questo funziona bene, ma in altre due situazioni correlate, non riesco a far funzionare le cose:

  1. Vorrei utilizzare HyperlinkedRelatedField. Questo campo richiede l'argomento view_name, qualcosa che non posso dichiarare poiché il nome della vista varia con il modello correlato. Ho risolto questo problema utilizzando SerializerMethodField, creando un'istanza di HyperlinkedIdentityField in fase di runtime e restituendo il suo metodo field_to_native (vedere lo snippet di seguito). Questo non si sente molto elegante.
  2. Vorrei nidificare l'oggetto correlato direttamente nella serializzazione dicendo event_object = SoAndSoSerializer(source='event_object'). L'unica soluzione che riesco a vedere è camminare ogni *Serializer che ho definito e verificare quale sia il modello corretto, quindi usarlo. Di nuovo, questo non si sente molto elegante.

Domande

è HyperlinkRelatedField pensato per funzionare su una relazione generica? Sto solo facendo un errore? C'è una soluzione ovvia per scegliere il giusto *Serializer che mi manca?

frammento di codice

La soluzione poco elegante di cui al punto 1 di cui sopra proiettile:

class WhateverSerializer(DefaultSerializer): 

    event_object_url = serializers.SerializerMethodField('get_related_object_url') 
    # ... 

    def get_related_object_url(self, obj): 
     obj = obj.event_object 
     default_view_name = '%(model_name)s-detail' 
     format_kwargs = { 
      'app_label': obj._meta.app_label, 
      'model_name': obj._meta.object_name.lower() 
     } 
     view_name = default_view_name % format_kwargs 
     s = serializers.HyperlinkedIdentityField(source=obj, view_name=view_name) 
     s.initialize(self, None) 
     return s.field_to_native(obj, None) 
+1

Si noti che è necessario utilizzare l'argomento "origine" per un campo solo se la sorgente è diversa dal nome del campo. Puoi lasciarlo nel caso 'event_object'. –

risposta

8

vostro diritto, quadro REST non supporta questi casi d'uso, e non è ovvio per me ciò che il il design sarebbe come se lo fosse. Probabilmente avresti bisogno di un registro implicito di model-> view (per il caso hyperlinked) e model-> serializer (per il caso annidato) che non credo sarei molto interessato.

Il modo più semplice per fare ciò che è necessario è probabilmente quello di sottoclasse ManyRelatedField e creare un tipo di campo personalizzato, ignorando to_native(self, obj) per serializzare ogni oggetto nel set esattamente come si desidera.

+0

Grazie per l'assegno di sanità Tom. Non ho fatto un tipo di domanda che ha una risposta 'corretta' (forma scadente), ma penso che tu abbia centrato il chiodo più o meno sulla testa. Saluti. –

Problemi correlati