2015-12-19 8 views
6

Questo è il mio ViewSet:Ricevere una KeyError per 'richiesta' in DRF serializzatore quando si utilizza detail_route nel mio ViewSet

class PostViewSet(viewsets.ModelViewSet): 
    serializer_class = PostSerializer 
    permission_classes = (IsAuthenticated, IsOwnerDeleteOrReadOnly) 

    def get_queryset(self): 
     return Post.objects.filter(location=self.request.user.userextended.location) 

    def perform_create(self, serializer): 
     serializer.save(owner=self.request.user, location=self.request.user.userextended.location) 

    def get_serializer_context(self): 
      """ 
      Extra context provided to the serializer class. 
      """ 
      return { 
       'format': self.format_kwarg, 
       'view': self, 
       'location': self.request.user.userextended.location 
      } 

    @detail_route(methods=['post'], permission_classes=[IsAuthenticated, IsFromLocation]) 
    def like(self, request, pk=None): 
     post = self.get_object() 
     post.usersVoted.add(request.user) 
     return Response(status=status.HTTP_204_NO_CONTENT) 

    @detail_route(methods=['get'], permission_classes=[IsAuthenticated, ValidPostPkInKwargs, IsFromPostLocation]) 
    def replies(self, request, pk=None): 
     post = self.get_object() 
     replies = post.postreply_set.all() 
     serializer = PostReplySerializer(replies, many=True) 
     return Response(serializer.data) 

E questo è il mio PostReplySerializer:

class PostReplySerializer(serializers.ModelSerializer): 
    owner = serializers.SlugRelatedField(slug_field='username', read_only=True) 
    voted = serializers.SerializerMethodField() 

    def get_voted(self, obj): 
     return self.context['request'].user in obj.usersVoted.all() 

    class Meta: 
     model = PostReply 
     fields = ('id', 'owner', 'post', 'voted', 'location') 

I punti di errore alla linea

return self.context['request'].user in obj.usersVoted.all() 

e dice:

KeyError at /URL/20/replies/ 
'request' 

Qualsiasi idea del perché DRF dica "richiesta" è un errore chiave anche se (dalla mia comprensione) dovrebbe essere automaticamente in self.context?

Si noti che PostViewSet funziona perfettamente bene per tutte le altre richieste (se ottengo un post, ottenere un elenco di messaggi ecc.). Semplicemente non funziona per replies.

risposta

4

Non è in self.context perché è stato sovrascritto get_serializer_context. L'oggetto request è collegato al contesto tramite questo metodo. Basta aggiungere request: self.request nella dichiarazione di reso di get_serializer_context per risolvere il problema. Dai un'occhiata all'implementazione predefinita di get_serializer_context qui https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/generics.py per saperne di più. Speranza che aiuta ..

EDIT Dal momento che si sta utilizzando serializzatore diversa (PostReplySerializer) in detail_route, è necessario creare un'istanza serializzatore come serializer = PostReplySerializer(replies, many=True, context={'request': self.request})

+0

Strano. Anche quando aggiungo "richiesta": self.request, "nell'istruzione return, ho ancora lo stesso errore. potrebbe avere qualcosa a che fare con il fatto che il serializzatore che sto usando nel mio dettaglio_route è diverso da quello che sto usando nel mio viewset? Modifica: anche quando rimuovo 'get_serializer_context()' completamente dal mio viewet e non lo sovrascrivo, ho ancora lo stesso errore per qualche motivo. – user2719875

+1

sì .. Questo perché si sta utilizzando un serializzatore diverso in detail_route. Prova a passare 'context = {'request': self.request}' durante la creazione dell'istanza serializer. come 'serializer = PostReplySerializer (replies, many = True, context = {'request': self.request})'. Questo risolverebbe il problema. –

+0

Oh ok grazie! Qualche idea sul perché il detail_route non riceva i contesti del serializzatore anche se fa parte dello stesso viewet? C'è qualche documentazione che la menziona? Sto chiedendo solo così posso capire cosa sta succedendo esattamente. Grazie in anticipo! – user2719875