Home > Software engineering >  Provide request data from view into serializer ModelViewSet Django
Provide request data from view into serializer ModelViewSet Django

Time:08-30

I try to make a custom list function inside ProductViewSet because I need to download an extra field - the highest product price in database. How can I provide the request argument from def list into serializer? I mean right now I get error 'NoneType' object has no attribute 'user' in this line: if request.user.is_authenticated.

So how can I fix it that he can read self.context.get('request') correctly?


class ProductViewSet(viewsets.ModelViewSet):
    ...

    def list(self, request):
        queryset = Product.objects.all()
        serializer = ProductSerializer(queryset, many=True)
        return Response(serializer.data)
class ProductSerializer(serializers.ModelSerializer):
   ...

    class Meta:
        model = Product
        ...

    
    def get_is_followed(self, obj):
        request = self.context.get('request')
        if request.user.is_authenticated:
            return Product.objects.filter(id=obj.id, followers=request.user.id).exists()

I want to work it like a default ModelViewSet list but with an extra field.

CodePudding user response:

You have used ModelViewSet which already has a serializer_class attribute. You can simply provide the serializer_class and the serializer context is taken care by DRF itself. So, instead of writing serializer = ProductSerializer(queryset, many=True) you should write in this way:

class ProductViewSet(viewsets.ModelViewSet):
    serializer_class = ProductSerializer
    queryset = Product.objects.all()

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

If your concern is only the request object as a context to the serializer then there is no need to override the list method in the ProductViewSet. By default three contexts (request, format and view) are passed to the serializer but if you need extra contexts then you can always override def get_serializer_context(self) method in the view. This is the default signature of the get_serializer_context:

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