Django rest framework - self.context doesn't have request attribute

Wendy picture Wendy · Jul 9, 2016 · Viewed 15.4k times · Source
class MyModelSerializer(serializers.ModelSerializer):
    field1 = serializers.CharField()
    field2 = serializers.SerializerMethodField('get_awesome_user')

    def get_current_user(self):
        request = self.context.get("request")
        if request and hasattr(request, "user"):
            return request.user
        return None

   def get_awesome_user(self, obj):
       user = self.get_current_user()
       ## use this user object, do some stuff and return the value
       return ...

My api(which uses authentication_classes and permission_classes) is using this serializer and the get_current_user function always returns None. when I debug it, I found that self.context is empty dictionary, i.e {}. to be double sure I also printed self.context.keys(), still it's empty list.

I followed this thread.

Get current user in Model Serializer

PS: I'm using djangorestframework==3.3.3, Django==1.9.1

EDIT: adding viewset code

class MyModelViewSet(viewsets.ModelViewSet):

    authentication_classes = (SessionAuthentication, BasicAuthentication, TokenAuthentication)
    permission_classes = (IsAuthenticated,)

    def list(self, *args, **kwargs):
         queryset = MyModel.objects.all()
         page = self.paginate_queryset(queryset)
         if page is not None:
             serializer = MyModelSerializer(page, many=True)
             return self.get_paginated_response(serializer.data)

         serializer = MyModelSerializer(queryset, many=True)
         return Response(serializer.data)

Answer

Boris Burkov picture Boris Burkov · Jul 9, 2016

How do you create serializer in your viewset's list() method? You should call

serializer = self.get_serializer(data=request.data)

to get your serializer context filled automatically as it is done in default implementation of this method in DRF mixins., but I have a feeling that you're just creating it manually, like this:

serializer = MyModelSerializer(instance)

So, to fix this, you should either call get_serializer(), or pass extra context argument to serializer constructor:

serializer = MyModelSerializer(instance, context={'request': request, ...})