2013-02-17 7 views
8

Ich habe den folgenden Serializer mit der Django REST Framework.Rest Framework Serializer-Methode

Das ist, was ich bisher haben ...

serializer.py

class ProductSerializer(serializers.ModelSerializer): 

    score = serializers.SerializerMethodField('get_this_score') 

    class Meta: 
     model = Product 
     fields = ('id', 'title', 'active', 'score') 

    def get_this_score(self, obj): 

     profile = Profile.objects.get(pk=19) 
     score = [val for val in obj.attribute_answers.all() if val in profile.attribute_answers.all()] 
     return (len(score)) 

urls.py

url(r'^products/(?P<profile_id>.+)/$', ProductListScore.as_view(), name='product-list-score'), 

Es gibt ein paar Probleme mit diesem Code-Schnipsel von Code.

1) Der Kinderwagen pk = 19 ist hardcoded sollte es self.kwargs['profile_id']. sein Ich habe versucht und versucht, aber ich weiß nicht, wie man Kwarg in die Methode übergeben und profil_id nicht funktionieren kann. d. h. ich kann es nicht von der URL abrufen.

2) Sollte dieser Code in Modellen enthalten sein? Ich habe versucht, zu Modellen hinzuzufügen, aber wieder kann die Argumente übergeben.

models.py dh Methode Klasse

 def get_score(self, profile): 

     score = [val for val in self.attribute_answers.all() if val in 
profile.attribute_answers.all()] 
      return len(score) 

Antwort

21

Serializer sind ein Kontext Wörterbuch übergeben, die die Ansicht Instanz enthält, so dass Sie die profile_id, indem Sie so etwas wie dies bekommen konnte:

view = self.context['view'] 
profile_id = int(view.kwargs['profile_id']) 

Aber in diesem Fall denke ich nicht, dass Sie das tun müssen, da 'obj' in jedem Fall auf die Profilinstanz gesetzt wird.

Und ja, Sie könnten stattdessen die Methode 'get_this_score' für die Modellklasse verwenden. Sie würden weiterhin das 'SerializerMethodField' benötigen, aber es würde einfach 'return obj.get_this_score (...)' aufrufen und alle Argumente aus dem Serializer-Kontext setzen.

Beachten Sie, dass der Kontext des Serializers auch 'request' enthält, so dass Sie bei Bedarf auch auf 'request.user' zugreifen können.

+1

Ich mag die Idee, dies in den Modellen zu haben. aber SerializerMethodField mit source = erlaubt mir nicht, die parms zu übergeben. Könnten Sie mir ein Beispiel für die Verwendung eines SerializerMethodFields geben und Anforderungsargumente sowie das Objekt an eine Modellmethode übergeben? das würde mir wirklich helfen zu verstehen. Danke. – jason

+0

Im Beitritt zu der Frage von @jason –

+0

in 'Aber in diesem Fall glaube ich nicht, dass Sie tun müssen, da 'obj' in jedem Fall auf die Profilinstanz gesetzt werden soll" meinst du 'Produkt' Beispiel vielleicht? – Pynchia

7

Um jason's Frageantwort auf Toms Antwort zu beantworten, können Sie auf das Anfrageobjekt über den gleichen Kontextmechanismus zugreifen. Sie referenzieren die Anforderungsobjekte aus der ModelMethod-Definition, die Sie nicht übergeben. Ich konnte dies verwenden, um auf das aktuelle request.user Objekt wie folgt zuzugreifen:

class ProductSerializer(serializers.ModelSerializer): 
    score = serializers.SerializerMethodField('get_this_score') 

    class Meta: 
     model = Product 
     fields = ('id', 'title', 'active', 'score') 

    def get_this_score(self, obj): 

     profile = self.context['request'].user 
     score = [val for val in obj.attribute_answers.all() if val in profile.attribute_answers.all()] 
     return (len(score)) 
+0

Danke Mann, deine Lösungen funktionieren für mich! –

+0

Wenn ich diesen Serializer mit CBV benutze, funktioniert es gut, aber wenn ich diesen Serializer mit FBV 'return Response ({'data': ProductSerializer (user_profiles, many = True) .data})' Ich bekomme Keyerror Request –

+0

gelöst von [einschließlich extra Kontext] (http://www.django-rest-framework.org/api-guide/serializers/#inclusive-extra-context) –