Django Rest框架 - APIView分页

时间:2016-03-06 18:29:31

标签: python django pagination django-rest-framework

我有一个非常简单的APIView,但我不知道如何在这里设置分页。 在这种情况下,我选择了Event给定的pk,然后我获得了分配给此NewsItems的所有Event

当我在pagination_class = LimitOffsetPagination的开头定义queryset时,

ListCreateAPIView正常工作。 queryset = Event.objects.all()但未使用自定义get

class EventNewsItems(APIView):
    pagination_class = LimitOffsetPagination

    def get(self, request, pk, format=None):

        #user = request.user
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

        serializer = NewsItemSerializer(news, many=True, context={'request':request})
        response = Response(serializer.data, status=status.HTTP_200_OK)
        return response

解决:

def get(self, request, pk, format=None):

    #user = request.user
    event = Event.objects.get(pk=pk)
    news = event.get_news_items().all()
    paginator = LimitOffsetPagination()
    result_page = paginator.paginate_queryset(news, request)
    serializer = NewsItemSerializer(result_page, many=True, context={'request':request})
    response = Response(serializer.data, status=status.HTTP_200_OK)
    return response

3 个答案:

答案 0 :(得分:8)

我在这个主题上创建了一个Q&A style example 作为一种总结:

通过使用Django Rest Frameworks源代码以及它们如何处理分页,我们在视图类中创建相同的方法并使用它们,就像您的解决方案使用默认方法一样:

  

取自上述文件:

from rest_framework.settings import api_settings
from rest_framework.views import APIView

class MyView(APIView):
    queryset = OurModel.objects.all()
    serializer_class = OurModelSerializer
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS # cool trick right? :)

    # We need to override get method to achieve 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)

        ... Do other stuff needed (out of scope of pagination)

    # Now add the pagination handlers taken from 
    #  django-rest-framework/rest_framework/generics.py

    @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) 

答案 1 :(得分:3)

另一种分页方法是使用Paginator类。

除了答案查询,您还必须设置要显示的页面数以及该页面将具有的元素范围。

页码和项目范围可以作为请求参数的一部分或通过您选择的方式提供。

以问题的情况为例:

from django.core.paginator import Paginator

class EventNewsItems(APIView):

    def get(self, request, pk, format=None):

        #user = request.user
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

         # -----------------------------------------------------------
        page_number = self.request.query_params.get('page_number ', 1)
        page_size = self.request.query_params.get('page_size ', 10)

        paginator = Paginator(news , page_size)
        serializer = NewsItemSerializer(paginator.page(page_number) , many=True, context={'request':request})
        # -----------------------------------------------------------

        response = Response(serializer.data, status=status.HTTP_200_OK)
        return response

答案 2 :(得分:0)

另一个选项将从分页类继承,而对视图类的更改较少:


class EventNewsItems(APIView, LimitOffsetPagination):

    def get(self, request, pk, format=None):
        event = Event.objects.get(pk=pk)
        news = event.get_news_items().all()

        results = self.paginate_queryset(news, request, view=self)
        serializer = NewsItemSerializer(results, many=True)
        return self.get_paginated_response(serializer.data)