2013-01-21 5 views
11

ProblemDjango REST Framework i stosunki generyczne

Mam model z następujących standardowych pól rodzajowe klucza obcego:

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

Według docs reszta ramowego, mogę wykonać następujące czynności, aby serialise to poprawnie:

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

działa to dobrze, jednak w dwóch innych związanych z sytuacjami, nie mogę dostać rzeczy robocze:

  1. Chciałbym użyć HyperlinkedRelatedField. To pole wymaga argumentu nazwa_widoku, coś, czego nie mogę zadeklarować, ponieważ nazwa widoku zmienia się w powiązanym modelu. Rozwiązałem to, używając SerializerMethodField, tworząc instancję HyperlinkedIdentityField w czasie wykonywania i zwracając jej metodę field_to_native (patrz fragment poniżej). To nie jest bardzo eleganckie.
  2. Chciałbym zagnieździć obiekt powiązany bezpośrednio w serializacji, mówiąc: event_object = SoAndSoSerializer(source='event_object'). Jedyne rozwiązanie, jakie widzę, to chodzić po każdym zdefiniowanym i sprawdzonym, który ma prawidłowy model, a następnie użyć tego. Ponownie, nie jest to bardzo eleganckie.

Pytania

jest HyperlinkRelatedField przeznaczona do pracy w całej relacji rodzajowe? Czy ja tylko popełniłem błąd? Czy istnieje oczywiste rozwiązanie polegające na tym, że brakuje mi właściwej odpowiedzi?

Code Snippet

nieeleganckie rozwiązanie o którym mowa w podpunkcie 1 powyżej:

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

Należy pamiętać, że do pola należy użyć tylko argumentu "source", jeśli źródło różni się od nazwy pola. Możesz go upuścić w przypadku "event_object". –

Odpowiedz

8

Prawo, ramy REST nie obsługuje tych przypadków użycia, a jego nie dla mnie oczywiste, co wyglądałby tak, jakby to wyglądało. Prawdopodobnie będziesz potrzebował niejawnego rejestru modelu-> widoku (dla przypadku z hiperłączem) i modelu-> serializera (dla przypadku zagnieżdżonego), co do którego nie sądzę, bym był bardzo zainteresowany.

Najprostszym sposobem zrobienia tego, czego potrzebujesz, jest prawdopodobnie podklasa ManyRelatedField i utworzenie niestandardowego typu pola, przesłaniając to_native(self, obj) w celu serializacji każdego obiektu w zestawie dokładnie w pożądany sposób.

+0

Dzięki za sprawdzenie zdrowia psychicznego Tom. Nie zadałem pytania, które ma "poprawną" odpowiedź (słaba forma), ale myślę, że uderzyłeś paznokciem mniej więcej w głowę. Twoje zdrowie. –