非泛型 ViewsViewset 上的高階分頁

這是一個高階主題,如果沒有先了解此頁面的其他示例,請不要嘗試

正如關於分頁的官方 Django Rest Framework中所述 :

只有在使用通用檢視或檢視集時,才會自動執行分頁。如果你使用常規 APIView,則需要自己呼叫分頁 API 以確保返回分頁響應。有關示例,請參閱 mixins.ListModelMixin 和 generics.GenericAPIView 類的原始碼。

但是如果我們想在非通用檢視/檢視集上使用分頁呢?

好吧,讓我們走下兔子洞吧:

  1. 第一站是官方的 Django Rest Framework 的儲存庫,特別是 django-rest-framework / rest_framework / generics.py 。這個連結指向的特定行向我們展示了框架的開發人員如何處理其泛型中的分頁。
    這正是我們將要用於我們觀點的內容!

  2. 讓我們假設我們有一個全域性分頁設定,如本頁介紹示例中所示,並假設我們有一個我們想要應用分頁的 APIView

  3. 然後在 views.py

    from django.conf import settings
    from rest_framework.views import APIView
    
    class MyView(APIView):
        queryset = OurModel.objects.all()
        serializer_class = OurModelSerializer
        pagination_class = 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)
    

現在我們有一個處理分頁的 APIView