如何在非通用视图/视图集中使用分页?

Posted

技术标签:

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

序幕:

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

Django Rest Framework - APIView Pagination Pagination not working in DRF APIView Django rest framework global pagination parameters not working for ModelViewSet

也可以在这里应用:

Combine ListModelMixin with APIView to show pagination

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

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


问题:

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

    REST_FRAMEWORK = 
        'DEFAULT_PAGINATION_CLASS': 
            'rest_framework.pagination.DESIRED_PAGINATION_STYLE',
        'PAGE_SIZE': 100
    
    

    为了不让我们的视图/视图集的代码膨胀,我们可以创建一个自定义的 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)
    

    然后在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 并且效果很好:***.com/questions/44048156/…(更新了带有相应链接的评论)

以上是关于如何在非通用视图/视图集中使用分页?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用图像视图制作无限分页滚动视图?

如何在 swift 中使用自定义导航栏制作三个分页视图

如何在swift 3中的表视图单元格中实现集合视图的分页?

如何在 iOS 的分页滚动视图中缩放图像?

如何在非刀片模板中显示雄辩的行?

当我在基于类的视图中应用过滤器时,如何在 django 中使用分页分页。网址总是不断变化我如何跟踪网址