2013-02-17 15 views
8

Mam następujący Serializer za pomocą Django REST Framework.Rest Framework Serializer Method

To, co mam tak daleko ...

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'), 

Istnieje kilka problemów z tym fragmencie kodu.

1) Wózek pk = 19 jest zakodowany powinien być self.kwargs['profile_id']. Próbowałem i próbowałem, ale nie wiem, jak przekazać kwarg do metody i nie mogę uzyskać właściwości profile_id do pracy. tj. nie mogę uzyskać tego z adresu URL.

2) Czy którykolwiek z tych kodów powinien być w modelach? Próbowałem dodawać do modeli, ale znowu mogę przekazać argumenty.

models.py czyli klasa metoda

 def get_score(self, profile): 

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

Odpowiedz

21

Serializers zapadają słownika kontekstu, który zawiera instancję widok, więc można uzyskać PROFILE_ID robiąc coś takiego:

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

Jednak w tym przypadku nie myślę, że musisz to zrobić, ponieważ "obj" będzie w każdym przypadku ustawione na instancję profilu.

I tak, można zamiast tego zastosować metodę "get_this_score" w klasie modelu. Nadal będziesz potrzebował "SerializerMethodField", ale po prostu wywoła "return obj.get_this_score (...)", ustawiając dowolne argumenty z kontekstu serializera.

Należy zauważyć, że kontekst serializatora zawiera również "żądanie", więc w razie potrzeby można również uzyskać dostęp do "request.user".

+1

Podoba mi się pomysł posiadania tego w modelach. ale SerializerMethodField za pomocą source = nie pozwala mi przekazać parm. czy mógłbyś mi podać przykład użycia SerializerMethodField i przekazywania args żądania oraz obiektu do metody modelu? to naprawdę pomogłoby mi zrozumieć. Dzięki Ci. – jason

+0

Dołączam do pytania @jason –

+0

w 'Jednak w tym przypadku nie myślę, że musisz to zrobić, ponieważ 'obj' będzie w każdym razie ustawione na instancję profilu 'masz na myśli przykład' Product'? – Pynchia

7

Aby odpowiedzieć na odpowiedź Jason na odpowiedź Toma, można uzyskać dostęp do obiektu żądania za pomocą tego samego mechanizmu kontekstowego, jak w przypadku. Użytkownik odwołuje się do obiektów żądania z definicji ModelMethod, nie przekazuje ich. Udało mi się użyć tego do uzyskania dostępu do bieżącego obiektu request.user, jak poniżej:

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

Dzięki stary, twoje rozwiązania działają dla mnie! –

+0

Kiedy używam tego serializera z CBV, działa dobrze, ale kiedy użyłem tego serializera z FBV 'return Response ({'data': ProductSerializer (user_profiles, many = True) .data})' Otrzymuję zgłoszenie keyerror –

+0

rozwiązane przez [w tym dodatkowy kontekst] (http://www.django-rest-framework.org/api-guide/serializers/#including-extra-context) –

Powiązane problemy