Django Rest Framework序列化器获取URL参数的问题
解决DRF分页场景下序列化器获取URL中user_id的问题
方案一:修改自定义分页器,支持传递额外Context
你的自定义分页器CustomPageNumberPagination的generate_response方法应该没处理序列化器的context参数,直接修改这个方法,让它接收并传递context即可:
修改分页器代码
class CustomPageNumberPagination(PageNumberPagination): def generate_response(self, queryset, serializer_class, request, **kwargs): page = self.paginate_queryset(queryset, request) if page is not None: # 获取视图传入的context,默认空字典 context = kwargs.get('context', {}) # 把request加入context(DRF序列化器默认会携带request到context) context['request'] = request serializer = serializer_class(page, many=True, context=context) return self.get_paginated_response(serializer.data) # 不分页场景同样传递context context = kwargs.get('context', {}) context['request'] = request serializer = serializer_class(queryset, many=True, context=context) return Response(serializer.data)
视图中调用时传递context
def get(self, request, post_id, post_language_id, user_id): ... paginator = CustomPageNumberPagination() # 传入包含user_id的context response = paginator.generate_response(language_liked_data, PostLanguageLikedSerializer, request, context={'user_id': user_id}) return response
方案二:直接从Request对象获取URL路径参数(更通用)
既然user_id是URL中的路径参数,你可以直接在序列化器中从request对象的parser_context里提取,不需要手动传context,分页/非分页场景都能用:
修改序列化器代码
class PostLanguageLikedSerializer(serializers.ModelSerializer): is_following = serializers.SerializerMethodField() ... class Meta: model = PostLanguageLike fields = [...,'is_following'] def get_is_following(self, obj): # 从request的路径参数中直接获取user_id user_id = self.context['request'].parser_context['kwargs']['user_id'] # 用exists()替代len(),查询性能更优 is_following = UserFollowing.objects.filter(user_id=user_id, following_user_id=obj.user.id).exists() return is_following
这个方案无需修改视图和分页器,逻辑更简洁,推荐使用。
方案三:将user_id附加到Request对象上
在视图中把user_id放到request的自定义属性中,序列化器直接从request读取:
视图代码修改
def get(self, request, post_id, post_language_id, user_id): # 把user_id附加到request对象 request.user_id = user_id ... paginator = CustomPageNumberPagination() response = paginator.generate_response(language_liked_data, PostLanguageLikedSerializer, request) return response
序列化器代码修改
def get_is_following(self, obj): user_id = self.context['request'].user_id is_following = UserFollowing.objects.filter(user_id=user_id, following_user_id=obj.user.id).exists() return is_following
注意:使用该方案时,要确保分页器的generate_response方法在实例化序列化器时,已将request传入context(DRF序列化器默认会自动包含request,只要分页器没覆盖这个逻辑即可)。
内容的提问来源于stack exchange,提问作者MdHassan413
相关产品推荐
相关产品推荐

