如何在非通用视图/视图集中使用分页? [英] How to use Pagination in a Non-Generic View/Viewset?
问题描述
序言:
我已经在多个帖子中看到了这个问题:
I have seen this question arising in more than one posts:
- Django Rest Framework - APIView Pagination
- Pagination not working in DRF APIView
- Django rest framework global pagination parameters not working for ModelViewSet
,也可以在此处应用:
我在SO文档中编写了一个示例,以统一上述问题的答案,但是由于文档将于2017年8月8日关闭,因此我将遵循
I have composed an example on SO Documentation to unify my answers in the above questions but since the Documentation will get shutdown on August 8 2017, I will follow the suggestion of this widely upvoted and discussed meta answer and transform my example to a self-answered post.
当然,我也很高兴看到任何其他方法!
Of course I would be more than happy to see any different approach as well!!
问题:
我想使用非通用视图/视图集(例如: APIView
)在Django Rest Framework项目上.
正如我在分页文档:
I want to use a Non Generic View/Viewset (eg: APIView
) on a Django Rest Framework project.
As I read on the pagination documentation:
仅当您使用通用视图或视图集时,才会自动执行分页.如果您使用常规
APIView
,则需要自己调用分页API,以确保您返回分页响应.有关示例,请参见mixins.ListModelMixin
和generics.GenericAPIView
类的源代码.
Pagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular
APIView
, you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for themixins.ListModelMixin
andgenerics.GenericAPIView
classes for an example.
我仍然可以继续使用非通用视图/视图集吗?
如何在其上执行分页?
Can I still continue using a non generic view/viewset?
How can I implement pagination on it?
推荐答案
我们无需重新发明轮子就能找到解决方案:
We can find a solution without the need to reinvent the wheel:
-
让我们看看如何实现
generics
分页: django-rest-framework/rest_framework/generics.py .
这正是我们将要用到的视图!
Let's have a look on how the
generics
pagination is implemented: django-rest-framework/rest_framework/generics.py.
That is exactly what we are going to use to our view as well!
让我们假设我们有一个全局分页设置,如下所示:
settings.py
:
Let's assume that we have a global pagination setup like the following in:
settings.py
:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':
'rest_framework.pagination.DESIRED_PAGINATION_STYLE',
'PAGE_SIZE': 100
}
为了不使视图/视图集的代码膨胀,我们可以创建一个自定义的mixin来存储我们的分页代码:
In order not to bloat our view/viewset's code, we can create a custom mixin to store our pagination code:
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
.
And now we have an APIView
with pagination.
这篇关于如何在非通用视图/视图集中使用分页?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!