【问题标题】:adding metadata to filtering in django rest framework在 django rest 框架中添加元数据进行过滤
【发布时间】:2014-05-31 10:29:05
【问题描述】:

我有一个通用的ListCreateAPIView 视图。我已经实现了一个执行搜索的get_queryset 函数。该函数解析查询,提取标签和术语并返回查询集。

def get_queryset(self):
        query = self.request.QUERY_PARAMS.get('query', None)

        # No deleted items
        queryset = Items.objects.filter(deleted__isnull=True)

        if query is None:
            return queryset

        predicates = []

        # Generate predicates from query       

        queryset = queryset.filter(reduce(__and__,predicates))
        return queryset

使用来自get_queryset 函数的数据将元数据添加到响应中的最佳方法是什么?

我正在寻找类似于分页工作方式的东西。

{
 query : {
     terms : ['term1','term2'], 
     tags  : ['tag1','tag2'] , 
    }
 results : [
      { name : 'item1', .... }
      { name : 'item2', .... }
   ]
}

编辑

所以我为过滤创建了一个自定义FilterBackend,现在我有了一个请求和响应的实例。查看 django rest 的分页代码,我看到它正在将结果包装在序列化程序中。分页被构建到视图类中,因此如果检测到分页器,fw 会调用序列化。看搜索 api 并没有产生任何新的想法。

我的问题仍然是,将元数据从过滤器后端添加到响应中的最佳且干扰最小的方式是什么?

我能想到的一种方法(也是我不喜欢的一种方法)是将元数据重载到过滤器后端的请求中,并在视图中覆盖 finalize_response - 毫无疑问,这是最糟糕的方法。

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    我不确定这是不是最好的方法,但我可能会覆盖 get 以简单地拦截响应对象并根据需要修改 response.data。像

    这样简单的东西
    from rest_framework import generics
    
    class SomeModelList(generics.ListCreateAPIView):
        """
        API endpoint representing a list of some things.
        """
    
        model = SomeModel
        serializer_class = SomeModelSerializer
    
        def get(self, request, *args, **kwargs):
            response = super(SomeModelList, self).get(request, *args, **kwargs)
    
            # redefine response.data to include original query params
            response.data = {
                'query': dict(request.QUERY_PARAMS),
                'results': response.data
            }
    
            return response
    

    如果您发现自己对多个列表视图重复此操作,您可以使用 Mixin 保持 DRY 并将其包含在您的列表 API 类中:

    from rest_framework import generics
    from rest_framework.mixins import ListModelMixin
    
    class IncludeQueryListMixin(ListModelMixin):
        def list(self, request, *args, **kwargs):
            response = super(IncludeQueryListMixin, self).list(request, *args, **kwargs)
    
            # redefine response.data to include original query params
            response.data = {
                'query': dict(request.QUERY_PARAMS),
                'results': response.data
            }
    
            return response
    
    
    class SomeModelList(IncludeQueryListMixin, generics.ListCreateAPIView):
        """
        API endpoint representing a list of some things.
        """
    
        model = SomeModel
        serializer_class = SomeModelSerializer
    

    【讨论】:

    • 当我试图拦截响应对象时,我收到“ContentNotRenderedError -- 响应内容必须先呈现才能访问。”不幸的是,我认为您需要覆盖调用 Response 的地方,以便您可以更改“数据”的格式。
    • @MarkChackerian 我不确定是什么导致了你的错误,但我已经用我验证可以使用 DRF 2.3.13 工作的完整示例更新了我的答案。可以再检查一下吗?
    • 我已重新检查并确认您的解决方案有效。当我尝试检查响应对象时仍然收到错误消息,但实际上不需要这样做。
    猜你喜欢
    • 2012-12-24
    • 2017-05-27
    • 1970-01-01
    • 2014-02-17
    • 2020-04-26
    • 2017-05-03
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多