【问题标题】:Pagination not working in DRF APIView分页在 DRF APIView 中不起作用
【发布时间】:2017-08-26 19:39:29
【问题描述】:

我正在使用APIView 获取和发布项目。
我想使用 Django Rest Framework 为我的 API 实现分页,但它不起作用。

我想每页显示 10 个项目,但是当我执行 api/v1/items?page=1 时,我会得到所有项目,如果我只是执行 api/v1/items,我会得到一个空列表。

这是我所做的:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

class ItemsAPIView(APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def get(self, request, format=None):
        """
        Return a list of all items of this user.
        """
        reply = {}
        page = request.GET.get('page')
        print ('page is', page)
        try:
            products = BaseItem.objects.owned_items().filter(owner=request.user)
            reply['data'] = OwnedItemSerializer(products, many=True).data

            items = BaseItem.objects.filter(owner=request.user)
            paginator = Paginator(items, 1)
            items_with_pagination = paginator.page(page)
            if page is not None:
                reply['data'].extend(ItemSerializer(items_with_pagination, many=True).data)
            reply['data'].extend(ItemSerializer(items, many=True).data)

【问题讨论】:

  • 嘿,@pythonBeginner 我想知道,你觉得任何答案有帮助吗?

标签: python django pagination django-rest-framework


【解决方案1】:

paginator = None为我工作

> class NotesViewSet(viewsets.ModelViewSet):    
>     queryset = Notes.objects.all()
>     serializer_class = NotesWriteSerializer
>     paginator = None

【讨论】:

  • 问题是关于APIView 这个例子没有解决的问题。
【解决方案2】:

非通用视图和视图集do not have pagination by default 如 django rest 框架文档中所述:

只有在您使用通用视图或视图集时才会自动执行分页。如果您使用常规的APIView,则需要自己调用分页 API 以确保返回分页响应。有关示例,请参阅 mixins.ListModelMixingenerics.GenericAPIView 类的源代码。

我编写了一个full example on enabling pagination on non generic views,其中包含有关如何实现此目的的代码:

class ItemsAPIView(APIView):
    permission_classes = (permissions.IsAuthenticated,)
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
    serializer_class = MyNewUnifiedSerializerClass

    def get(self, request):
        user_items =  BaseItem.objects.filter(
                          owner=request.user
                      ).distinct()
        page = self.paginate_queryset(user_items)

        if page is not None:
            serializer = self.serializer_class(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(user_items, many=True)
        return Response(serializer.data)

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

更多详情请查看example link provided

【讨论】:

    【解决方案3】:

    扩展 GenericAPIView 而不是 APIView 并在GenericAPIView中定义pagination_class

    【讨论】:

      【解决方案4】:

      您可以让您的生活更轻松,只需使用 ListView。通过覆盖 render_to_response 您可以使其输出 json 而不是 HTML。它为您完成所有分页。

      from django.core import serializers
      from django.views.generic import ListView
      
      class MyListView(JSONResponseMixin, ListView):
          model = models.BaseItem    
          paginate_by = 10  
      
          def render_to_response(self, context):
              return JsonResponse(
                  serializers.serialize("json", context),
                  **response_kwargs
              )
      

      【讨论】:

      • 我的 APIView 中使用了两个序列化程序和一个扩展函数。它以不同的方式完成。如果它只是使用 model.objects.all(),我会更喜欢 ListView。
      • 然后在get_context_data(self, **kwargs):中添加您需要的任何其他内容
      猜你喜欢
      • 2018-06-12
      • 2021-11-25
      • 1970-01-01
      • 2018-05-21
      • 2021-09-25
      • 2011-03-04
      • 2015-11-24
      • 1970-01-01
      • 2019-05-09
      相关资源
      最近更新 更多