如何在非通用视图/视图集中使用分页? [英] How to use Pagination in a Non-Generic View/Viewset?

查看:91
本文介绍了如何在非通用视图/视图集中使用分页?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

序言:

我已经在多个帖子中看到了这个问题:

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.ListModelMixingenerics.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 the mixins.ListModelMixin and generics.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:

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

  1. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆