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
最佳答案
的确,尽管从ModelViewSet
和GenericViewSet
继承了分页,但默认情况下在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
是响应页面大小的当前设置。