【问题标题】:How to use Pagination in a Non-Generic View/Viewset?如何在非通用视图/视图集中使用分页?
【发布时间】:2018-01-22 01:31:53
【问题描述】:

序幕:

我在不止一篇帖子中看到过这个问题:

也可以在这里应用:

我在 SO 文档上编写了一个示例来统一我在上述问题中的答案,但由于文档将于 2017 年 8 月 8 日关闭,我将遵循 this widely upvoted and discussed meta answer 的建议并将我的示例转换为自我回答的帖子.

当然,我也很乐意看到任何不同的方法!


问题:

我想在 Django Rest Framework 项目中使用非通用视图/视图集(例如:APIView)。
正如我在pagination documentation 上看到的:

仅当您使用通用视图或视图集时,才会自动执行分页。如果您使用常规的APIView,则需要自己调用分页 API 以确保返回分页响应。有关示例,请参阅 mixins.ListModelMixingenerics.GenericAPIView 类的源代码。

我还能继续使用非通用视图/视图集吗?
怎么实现分页?

【问题讨论】:

    标签: python django pagination django-rest-framework


    【解决方案1】:

    我们无需重新发明轮子就能找到解决方案:

    1. 让我们看看generics分页是如何实现的: django-rest-framework/rest_framework/generics.py.
      这也正是我们要用于视图的内容!

    2. 假设我们有一个全局分页设置,如下所示:
      settings.py:

      REST_FRAMEWORK = {
          'DEFAULT_PAGINATION_CLASS': 
              'rest_framework.pagination.DESIRED_PAGINATION_STYLE',
          'PAGE_SIZE': 100
      }
      
    3. 为了不让我们的视图/视图集的代码膨胀,我们可以创建一个自定义的 mixin 来存储我们的分页代码:

      class MyPaginationMixin(object):
      
          @property
          def paginator(self):
              """
              The paginator instance associated with the view, or `None`.
              """
               if not hasattr(self, '_paginator'):
                   if self.pagination_class is None:
                       self._paginator = None
                   else:
                       self._paginator = self.pagination_class()
               return self._paginator
      
           def paginate_queryset(self, queryset):
               """
               Return a single page of results, or `None` if pagination 
               is disabled.
               """
               if self.paginator is None:
                   return None
               return self.paginator.paginate_queryset(
                   queryset, self.request, view=self)
      
           def get_paginated_response(self, data):
               """
               Return a paginated style `Response` object for the given 
               output data.
               """
               assert self.paginator is not None
               return self.paginator.get_paginated_response(data)
      
    4. 然后在views.py:

      from rest_framework.settings import api_settings
      from rest_framework.views import APIView
      
      from my_app.mixins import MyPaginationMixin
      
      class MyView(APIView, MyPaginationMixin):
          queryset = OurModel.objects.all()
          serializer_class = OurModelSerializer
          pagination_class = api_settings.DEFAULT_PAGINATION_CLASS 
      
          # We need to override the get method to insert pagination
          def get(self, request):
              ...
              page = self.paginate_queryset(self.queryset)
              if page is not None:
                  serializer = self.serializer_class(page, many=True)
                  return self.get_paginated_response(serializer.data)
      

    现在我们有了一个带有分页功能的APIView

    【讨论】:

    • 'NoneType' 对象没有属性 'paginate_queryset'。我收到此错误
    • @Thameem 没有一些代码来帮助你看看你做了什么有点困难......如果问题仍然存在,请考虑在 SO 上提出问题。
    • @thanks 你的消息我错过了这个回复返回 self.get_paginated_response(serializer.data)。谢谢。它现在工作
    • 这个页面至今仍在拯救生命。
    • @OpeyemiOdedeyi 我已经尝试使用django-filters 模块:django-filter.readthedocs.io/en/master 并且效果很好:stackoverflow.com/questions/44048156/…(更新了带有相应链接的评论)
    猜你喜欢
    • 2015-04-21
    • 1970-01-01
    • 2020-05-25
    • 2021-03-07
    • 2017-11-25
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多