【问题标题】:Django rest framework global pagination parameters not working for ModelViewSetDjango rest框架全局分页参数不适用于ModelViewSet
【发布时间】:2017-11-27 01:55:35
【问题描述】:

DRF 文档声明:

只有在您使用通用视图或视图集时才会自动执行分页。

但我使用的是继承自 ViewSetModelViewSet,所以我告诉自己“酷,我所要做的就是将它添加到我的 settings.py”:

'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 12, # for 12-col grid css frameworks

但是,这不起作用。
如果我为 27 个项目发送 GET 请求,它会返回所有项目(在可浏览的 API 和 json 中)。

  • 我是否认为我应该只在 12 岁时被退回?
  • 子问题: PAGE_SIZE 是每页返回的顶级对象的数量,对吗?我看到了一些PAGINATE_BY 的例子,但它 the source 中没有,所以我认为它已被弃用?

我正在使用 DRF 3.6.3、django 1.11.2。

编辑:我的设置:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 12,
}

我还在ModelViewSet 类中添加了pagination_class = PageNumberPagination,但没有效果。

以下是来自 shell 的验证,即 Pagination 类确实知道它应该提供的页面大小:

>>> from rest_framework.pagination import PageNumberPagination
>>> p = PageNumberPagination()
>>> p.max_page_size
>>> print(p.page_size)
12

【问题讨论】:

标签: python django pagination django-rest-framework


【解决方案1】:

它应该工作。 如果没有并且您没有拼写错误,请查看服务器日志,您可能会发现一些信息告诉您没有顺序的分页将不起作用:

xxxx/django/core/paginator.py:112: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: ....

为了解决这个问题,请确保在模型的 Meta 中指定排序或在 ModelViewSetqueryset 中设置 order_by

【讨论】:

  • 我有一个无序的查询集,但从框架的角度来看,我不会认为这很重要。我现在订购了它,但它没有改变任何东西。我在原始问题中添加了更多调试信息,但我还没有解决为什么某些设置(分页、渲染器)似乎没有被拾取。
【解决方案2】:

尽管继承自 GenericViewSetListMixin,但默认情况下分页在 ModelViewSet 上不起作用。您需要手动添加:

我编写了一个 Q&A style example 来解决这个问题,并在 ModelViewSet 类上对其进行了测试。

我稍微总结一下:

  1. 创建一个自定义 mixin 以利用 pagination_class:

    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)
    
  2. 让您的视图集扩展该 mixin 并覆盖 ModelViewSetlist() 方法:

    class MyViewset(MyPaginationMixin, viewsets.ModelViewSet):
        # since you are setting pagination on the settings, use this:
        pagination_class = settings.DEFAULT_PAGINATION_CLASS
    
        def list(self, request, *args, **kwargs):
            response = dict(
                super(MyViewSet, self).list(self, *args, **kwargs).data)
    
            page = self.paginate_queryset(response['results'])
            if page is not None:
                serializer = self.serializer_class(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                # Something went wrong here...
    

当然,您需要根据自己的需要校准此解决方案,但这会为ModelViewSet 添加分页。


对于子问题,@Linovia 的评论是正确的,PAGINATE_BY 已弃用,PAGE_SIZE 是响应页面大小的当前设置。

【讨论】:

    猜你喜欢
    • 2018-01-09
    • 1970-01-01
    • 2017-11-06
    • 2021-10-13
    • 2016-03-29
    • 2019-01-09
    • 1970-01-01
    • 2014-12-31
    • 2020-12-20
    相关资源
    最近更新 更多