【问题标题】:Django rest framework: how to turn off/on pagination in ModelViewSetDjango rest 框架:如何在 ModelViewSet 中关闭/打开分页
【发布时间】:2017-11-06 07:18:13
【问题描述】:

我使用Django REST frameworkdjangorestframework-csv 并具有默认分页设置,但是当请求格式为“CSV”时,分页中不需要。可以通过以下方式禁用分页:

pagination_class = None

可以动态更改吗?

class ObjectViewSet(BaseViewSet, viewsets.ModelViewSet):

    queryset = Object.objects.none()
    serializer_class = ObjectSerializer
    pagination_class = None # if format is "CSV"
    # pagination_class = None # if fromat isn't "CSV"

谢谢。

【问题讨论】:

  • 只是在query_params中没有page_size时发现一个错误,提出keyerror。我已经更新了新代码,请复制新的。

标签: django csv pagination django-rest-framework


【解决方案1】:

一种选择是通过设置no_page 查询参数来动态禁用视图上的分页:

def paginate_queryset(self, queryset, request, view=None):
    if 'no_page' in request.query_params:
        return None

    return super().paginate_queryset(queryset, request, view)

【讨论】:

  • 它不再工作了(至少在最新版本中没有),看看我的回答
【解决方案2】:

如果您只是想通过客户端动态打开或关闭分页,您可以自定义 Pagination 类为:

class Pagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    max_page_size = 100

    def get_page_size(self, request):
        if self.page_size_query_param:
            page_size = min(int(request.query_params.get(self.page_size_query_param, self.page_size)),
                        self.max_page_size)
            if page_size > 0:
                return page_size
            elif page_size == 0:
                return None
            else:
                pass
        return self.page_size

使用这个类作为你的 pagination_class,你可以通过请求 url "http://www.example.com/some_object/?page_size=0" 关闭分页,?page_size=0 将禁用分页。 如果你只是想在请求格式为 CVS 时禁用分页,你可以试试 danilke 说的。

【讨论】:

  • 这就像一个魅力;问题:是否可以禁用分页但保留分页结构?我的意思是,在生成的 JSON 中将数据数组保持在相同的键下?谢谢
【解决方案3】:

这个解决方案对我有用

DRF 版本:3.11.0

Django 版本:2.2.7

默认情况下分页是有效的,但是当我传递查询参数“no_page”时,分页将被禁用: 喜欢:http://localhost:8000/api/city/?no_page

class CityListView(generics.ListCreateAPIView):
    serializer_class = serializers.CitySerializer
    def paginate_queryset(self, queryset, view=None):
        if 'no_page' in self.request.query_params:
            return None
        else:
            return self.paginator.paginate_queryset(queryset, self.request, view=self)

【讨论】:

    【解决方案4】:

    它不再工作了(至少在最新版本中没有),你应该做类似的事情

     def paginate_queryset(self, queryset, request, view=None):
         if 'page' not in request.query_params:
                return queryset
         return super().paginate_queryset(queryset)
    

    并在列表方法中使用self.paginate_queryset(queryset, request)调用函数

    【讨论】:

    • 值得一提的是您的 DRF 版本,因为这在 3.11 上不起作用,似乎 API 经常更改!
    【解决方案5】:

    您只需在课堂上使用pagination_class = None

    class MyClassBasedView(ModelViewSet):
        pagination_class = None
    

    【讨论】:

      【解决方案6】:

      解决办法是:

      class PaginatedCSVRenderer (CSVRenderer):
          results_field = 'results'
      
          def render(self, data, *args, **kwargs):
              if not isinstance(data, list):
                  data = data.get(self.results_field, [])
              return super(PaginatedCSVRenderer, self).render(data, *args, **kwargs)
      

      比:

      class ObjectViewSet(BaseViewSet, viewsets.ModelViewSet):
      
          queryset = Object.objects.none()
          serializer_class = ObjectSerializer
          renderer_classes =  (JSONRenderer, PaginatedCSVRenderer)
      

      并从设置中删除:

         'PAGE_SIZE': 10,
      

      【讨论】:

        【解决方案7】:

        也许是一种更面向未来的方法 - 打开 my_venv/lib/python3.8/site-packages/rest_framework/generics.py - 替换 my_venv 和您的 Python 版本,滚动到第 165 行附近并复制 paginate_queryset 的方法签名。还要检查它返回的内容 if self.paginator is None - 如果你想禁用分页,那就是返回的内容。

        在 DRF 3.11 上,父方法签名是 paginate_queryset(self, queryset),而 if self.paginator is None 它返回 None,所以我使用了:

        def paginate_queryset(self, queryset):
            if 'page_id' in self.request.query_params:
                return None
            return super().paginate_queryset(queryset)
        

        我还没有测试过,但我猜 OP 问题的答案是(假设一个相当默认的 DRF 配置):

        if ('format' in self.request.query_params and 
                self.request.query_params['format'] == 'csv'):
        

        【讨论】:

          猜你喜欢
          • 2015-10-25
          • 2016-08-01
          • 2015-04-12
          • 1970-01-01
          • 2017-11-27
          • 1970-01-01
          • 2014-08-30
          • 2016-06-20
          • 2020-12-20
          相关资源
          最近更新 更多