首页 > 解决方案 > 访问 ViewSet 对象列表以向序列化程序提供额外的上下文

问题描述

我正在尝试将上下文添加到ModelViewSet依赖于上下文中当前分页对象列表的序列化程序中。我会用一个例子来解释。

我正在构建一个viewsets.ModelViewSet列出Users 和一个favorite_foods. 然而——通过 API 访问的一些外部微服务中用户最喜欢的食物列表。构建一个 ViewSet 来收集对象并在每个对象上执行 HTTP 请求是微不足道的,我们可以这样做:

class UserViewSet(viewsets.ViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class UserSerializer(serializers.ModelSerializer):
     favorite_foods = serializers.SerializerMethodField()

     def get_favorite_foods(self, instance):
         # performs an HTTP call and returns a list[] of foods. 
         return evil_coupled_microservice_client.get_user_food_list(instance)
    
     class Meta:
        model = User
        fields = ('id', 'name', 'favorite_foods')

问题是(除了一些丑陋的基础设施耦合)这将使 HTTP 请求计数等于页面大小。相反,如果我可以在一个 HTTP 调用中为页面上的所有用户预取最喜欢的食物列表,然后将它们添加到上下文中,那就太好了,如下所示:

class UserViewSet(viewsets.ViewSet):
    def get_serializer_context(self): 
        context = super().get_serializer_context()
        users = <-- This is where I want to know what users are in the current filtered, paginated response. 
        users_food_dict = evil_coupled_microservice_client.get_many_users_food_list(users)
        context.update({'usesr_foods': users_food_dict})
        return context

但是-似乎没有任何方法可以获取将要序列化的对象列表。尽管(我相当确定)get_serializer_context在查询集被过滤和分页之后被调用,但我不确定如何访问它,而无需基于 query_params 和附加到类的其他部分对查询集进行一些真正的黑客重新编译。

标签: django-rest-framework

解决方案


我将发布我当前的解决方案。这并不可怕,但我仍然希望有一个更清洁的内置。

class UserViewSet(viewsets.ViewSet): 
    ...
    def list(self, request, *args, **kwargs):
        # Overrwite `ListModelMixin` and store current set
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            self.current_queryset = page
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        self.current_queryset = queryset
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

到目前为止,这是未经测试的(例如,不确定 Detail 端点上的功能)允许current_queryset在序列化程序上下文中获取 。


推荐阅读