【问题标题】:Restrict the initial queryset to objects in pagination in django-restframework将初始查询集限制为 django-rest 框架中分页中的对象
【发布时间】:2014-11-02 03:37:44
【问题描述】:

我正在使用django-rest-framework 定义ModelViewSet
在呈现响应之前,我需要覆盖默认查询集以对查询集对象执行一些处理。

这个过程很耗时,所以我想只在由于分页响应而对消费者实际可用的对象上执行它,而不是将此过程应用于 所有对象并应用分页AFTER完成我的处理,我可以注意到(如果我错了,请纠正我)是 DRF 中的默认行为。


简而言之,我需要的是:

如果默认查询集是1000 objects,但分页限制为25 objects per page,我只想应用我的流程那些25 objects。请注意,除了分页之外,没有其他限制可以减少对象的最终数量。

有没有办法做到这一点?
在这种情况下,覆盖默认查询集是一个坏主意吗?

谢谢!

【问题讨论】:

  • 嘿,@Gerard,我已经为你的问题添加了一个(非常)迟到的答案。看看吧。

标签: python django pagination django-rest-framework


【解决方案1】:

没有“简单”的方法可以做到这一点。在 Django REST framework 中,分页与渲染的方法相同。

所以我想最好的办法是定义自己的 Viewset 并重新声明 list 方法:

from rest_framework.viewssets import ModelViewSet

class MyModelViewSet(ModelViewSet):

  def list(self, request, *args, **kwargs):
    self.object_list = self.filter_queryset(self.get_queryset())                
    if not self.allow_empty and not self.object_list:                           
      warnings.warn(                                                          
        'The `allow_empty` parameter is due to be deprecated. '             
        'To use `allow_empty=False` style behavior, You should override '   
        '`get_queryset()` and explicitly raise a 404 on empty querysets.',  
        PendingDeprecationWarning
      )              
      class_name = self.__class__.__name__                                    
      error_msg = self.empty_error % {'class_name': class_name}
      raise Http404(error_msg)                                                

    page = self.paginate_queryset(self.object_list)                             


    ## INSERT YOUR CODE HERE


    if page is not None:
      serializer = self.get_pagination_serializer(page)                       
    else:       
      serializer = self.get_serializer(self.object_list, many=True)           

    return Response(serializer.data)     

【讨论】:

    【解决方案2】:

    理论:

    如前所述:

    姜戈querysets are lazy.
    它们仅在绝对需要时才访问数据库(就像您在查询和分页之前进行处理时一样。)。

    DRF的分页过程分为两部分:

    • paginate_queryset
    • get_paginated_response

    我们可以根据需要选择覆盖哪个部分(参见实践部分)


    练习:

    根据您真正想要处理的内容,有两种选择。

    为此,我假设我们将扩展/覆盖 LimitOffsetPagination 类,这对于一个示例来说更容易,但相同的原则适用于所有其他 DRF 分页。

    1. 处理模型对象:

      如果您希望在模型对象上执行预处理并在您的数据库上永久保存,则需要覆盖 paginate_queryset 方法:

      class MyPaginationMethod(LimitOffsetPagination):
      
          def paginate_queryset(self, queryset, request, view=None):
              self.count = _get_count(queryset)
              self.limit = self.get_limit(request)
              if self.limit is None:
                  return None
      
              self.offset = self.get_offset(request)
              self.request = request
              if self.count > self.limit and self.template is not None:
              self.display_page_controls = True
      
              if self.count == 0 or self.offset > self.count:
                  return []
      
              """
              Do your processing here on the  
              queryset[self.offset:self.offset + self.limit]
              Which has actually self.limit (e.g 25) amount of objects.
              """
      
              return list(YOUR_PROCESSED_QUERYSET)
      
    2. 处理分页响应:

      如果您希望对响应执行预处理并且 NOT 在您的数据库中永久存在,则需要覆盖 get_paginated_response 方法:

      class MyPaginationMethod(LimitOffsetPagination):
      
          def get_paginated_response(self, data):
              """
              Do your processing here on the data variable.
              The data is a list of OrderedDicts containing every object's
              representation as a dict.
              """
              return Response(OrderedDict([
                  ('count', self.count),
                  ('next', self.get_next_link()),
                  ('previous', self.get_previous_link()),
                  ('results', YOUR_PROCESSED_DATA)
              ]))
      

    【讨论】:

      猜你喜欢
      • 2016-01-10
      • 2015-05-08
      • 1970-01-01
      • 2016-04-23
      • 2016-08-06
      • 2014-12-19
      • 2014-09-19
      • 2017-03-27
      • 1970-01-01
      相关资源
      最近更新 更多