DRF文档指出:


  仅在使用通用视图或视图集时才自动执行分页。


但是我使用的是从ModelViewSet继承的ViewSet,所以我告诉自己“很酷,我要做的就是将其添加到我的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,
}


我也将pagination_class = PageNumberPagination添加到ModelViewSet类,但没有任何效果。

这是来自Shell的验证,其中Pagination类确实知道应该提供的页面大小:

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

最佳答案

的确,尽管从ModelViewSetGenericViewSet继承了分页,但默认情况下在ListMixin上分页不起作用。您需要手动添加:

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

我将总结一下:


创建一个自定义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)

使您的视线扩展该混合,并覆盖list()ModelViewSet方法:

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是响应页面大小的当前设置。

10-06 15:48