sivaperumal10000
sivaperumal10000

Reputation: 69

How to get the current user object inside a Serializer method field in Django (while doing GET request)?

Below is my Serialzer method where I need the current user object to perform a logic,but it throws keyerror 'request'
I have tried all the possible solution's from stack over flow , but no luck I am new to django edit: I have posted the full code now , please check and knbldy help me in sorting this out

views.py

class Allview1(APIView,LimitOffsetPagination):
 permission_classes = (permissions.IsAuthenticated,)
 @swagger_auto_schema(
 query_serializer=PaginationSerializer,
 responses={status.HTTP_200_OK: []},
 operation_id="all_comments",
 )
 def get(self, request, *args, **kwargs):
 flag = kwargs['flag']
 pk = uuid.uuid4()
 start_time = dt.datetime.now()
 comment_id = request.GET.get('comment_id', '')
 #print(f" Request call for {__class__.__name__} {flag} | start_time : {start_time} | (Request_id : {pk}) ")
 logger.info(f" Request call for {__class__.__name__} {flag} | start_time : {start_time} | (Request_id : {pk}) ")


 response = {}
 today_max = dt.datetime.combine(dt.date.today(), dt.time.max)
 time_threshold = dt.datetime.now() - timedelta(days=1)
 threedays = dt.datetime.today() - timedelta(days=3)

 if flag == 'rec':
 recent_comments=redis_client.get("feeds:rec_comments")
 if recent_comments and int(request.GET.get('limit'))<=30:
 print("from cache")
 rec=pickle.loads(recent_comments)

 else:
 print("usual call")
 silenced_comments = StockUserComments.objects.filter(edit_type=EditTypeEnum.SILENCED_POST).values_list('id')
 private_users = list(ProfileSettings.objects.select_related('owner').filter(profile_public_discovery=False).values_list('owner__id', flat=True))

 rec = StockUserComments.objects.filter(Q(comment_text__length__gte=125) | Q(edit_type=EditTypeEnum.OUTLOOK)).exclude(user_id__in=private_users).exclude(id__in=silenced_comments).order_by("-date")

 cache_obj = redis_client.get("feeds:rec_comments")
 if not cache_obj:
 cache_obj = pickle.dumps(rec[:30])
 redis_client.set("feeds:rec_comments", cache_obj, ex=1800)

 results = self.paginate_queryset(rec, request, view=self)
 recent_comments = StockUserCommentsOutputSerializer1(results,many=True,context={'request':request})
 response["recently_discussed"] = recent_comments.data

 if flag == 'top':
 top_comments = redis_client.get("feeds:top_comments")
 if top_comments and int(request.GET.get('limit'))<=30:
 print("from cache")
 all = pickle.loads(top_comments)

 else:
 print("Usual call")
 silenced_comments = StockUserComments.objects.filter(edit_type=EditTypeEnum.SILENCED_POST).values_list('id')
 private_users = list(ProfileSettings.objects.select_related('owner').filter(profile_public_discovery=False).values_list('owner__id', flat=True))
 featured = StockUserComments.objects.filter(f_date__gte=time_threshold,edit_type=EditTypeEnum.FEATURED_POST).order_by("-f_date")

 qs = StockUserComments.objects.filter(date__gte=threedays).exclude(user_id__in=private_users).exclude(upvote__exact=0).exclude(Q(id__in=silenced_comments) | Q(id__in=featured)).order_by("-upvote")
 latest =StockUserComments.objects.filter(Q(comment_text__length__gte=125) | Q(edit_type=EditTypeEnum.OUTLOOK)).exclude(id__in=silenced_comments).exclude(id__in=qs).order_by("-date")
 featured = StockUserComments.objects.filter(f_date__gte=time_threshold,edit_type=EditTypeEnum.FEATURED_POST).order_by("-f_date")
 all =list(chain(featured,qs,latest))
 #print(all)
 cache_obj=redis_client.get("feeds:top_comments")
 if not cache_obj:
 cache_obj=pickle.dumps(all[:30])
 redis_client.set("feeds:top_comments", cache_obj,ex=1800)


 results = self.paginate_queryset(all, request, view=self)
 overall_comments = StockUserCommentsOutputSerializer1(results,many=True,context={'request':request})
 response["top_comments"] = overall_comments.data

 end_time = dt.datetime.now()
 #print(f" Response call for {__class__.__name__} {flag} | end_time : {end_time} | overall_time_taken : {end_time - start_time} | (Request_id : {pk}) ")
 logger.info(f" Response call for {__class__.__name__} {flag} | end_time : {end_time} | overall_time_taken : {end_time - start_time} | (Request_id : {pk}) ")

 return self.get_paginated_response(response)
 

serialzers.py

class StockUserCommentsOutputSerializer1(EnumChoiceModelSerializerMixin,serializers.ModelSerializer):
 user_detail = UserDetailSerializer(source='user',allow_null=True, required=False)
 replys = serializers.SerializerMethodField()
 ticker_logo = serializers.SerializerMethodField()
 tuser = TUserSerializer(many=True, allow_null=True, required=False)
 tsymbol = TSymbolSerializer(many=True, allow_null=True, required=False)
 company_name = serializers.SerializerMethodField()
 symbol_id=serializers.CharField(source='symbol')
 can_vote=serializers.SerializerMethodField()

 class Meta:
 model = StockUserComments
 fields = ['id', 'symbol_id','company_name', 'ticker_logo', 'comment_text', 'date', 'user_detail', 'replys', 'upvote', 'can_vote','parent','tuser','tsymbol','edit_type','outlook']

 def get_ticker_logo(self, obj):
        if obj.symbol:
            if obj.symbol.logo_url:
                return obj.symbol.logo_url
            else:
                return None
        else:
            return None


    def get_company_name(self, obj):
        if obj.symbol:
            if obj.symbol.name:
                return obj.symbol.name
            else:
                return None
        else:
            return None

    def get_replys(self, obj):
        queryset = StockUserComments.objects.filter(parent_id=obj.id).order_by('date')
        serializer = StockUserCommentsOutputSerializer1(queryset, many=True)
        return serializer.data

    def get_can_vote(self,obj):
        user = self.context['request'].user
        print(user)
        if obj.id and user:
            voter_data = CommentVotes.objects.filter(voter=user, comment=obj.id)
        if len(voter_data) > 0:
            return False
        else:
            return True

error

Traceback (most recent call last):
  File "E:\stocktalk-api-platform\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\django\views\generic\base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\views.py", line 476, in raise_uncaught_exception
    raise exc
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "E:\stocktalk-api-platform\apps\stock_dashboard\views.py", line 756, in get
    response["recently_discussed"] = recent_comments.data
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 760, in data
    ret = super().data
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 260, in data
    self._data = self.to_representation(self.instance)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 677, in to_representation
    return [
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 678, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 529, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\fields.py", line 1905, in to_representation
    return method(value)
  File "E:\stocktalk-api-platform\apps\stock_comments\serializers.py", line 178, in get_replys
    return serializer.data
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 760, in data
    ret = super().data
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 260, in data
    self._data = self.to_representation(self.instance)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 677, in to_representation
    return [
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 678, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\serializers.py", line 529, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "E:\stocktalk-api-platform\venv\lib\site-packages\rest_framework\fields.py", line 1905, in to_representation
    return method(value)
  File "E:\stocktalk-api-platform\apps\stock_comments\serializers.py", line 181, in get_can_vote
    user = self.context['request'].user
KeyError: 'request'
[30/Aug/2021 21:02:49] "GET /api/v1/dashboard/all_comments1/rec/?limit=10&offset=0 HTTP/1.1" 500 25528

Upvotes: 0

Views: 2158

Answers (3)

Sukhpreet Singh
Sukhpreet Singh

Reputation: 696

Add the __init__ method to your serializer so as to make context a class variable. Then you can access the context passed as self.context in the serializer methods. Try adding the following lines to serialzier class

def __init__(self, *args, **kwargs):
    self.context = kwargs.get('context', None)
    super(AssessmentListSerializer, self).__init__(*args, **kwargs)
    

you should still add checks to your methods hasattr(context, 'request') to avoid any 500 errors.

Upvotes: 1

Ashin Shakya
Ashin Shakya

Reputation: 776

You will have to directly pass request in context of the serializer as below.

SerializerClass(..., context={'request':request})

But if you use GenericAPIView, this behaviour is inherent and can access request directly in your serializer.

Add context in your serializer.

def get_replys(self, obj):
    queryset = StockUserComments.objects.filter(parent_id=obj.id).order_by('date')
    # Here
    serializer = StockUserCommentsOutputSerializer1(queryset, many=True, context=self.context)
    return serializer.data

Upvotes: 1

rrretry
rrretry

Reputation: 113

There's many ways to pass context to nested serializer. If you use for many instances easiest is to wrap your nested serializer(CommentsOutputSerializer1 with ListField). It will pass context of main serializer to nested by default.

https://stackoverflow.com/a/40260330/11354529

Upvotes: 2

Related Questions