django-rest-framework實現三種分頁

我們通常在使用Django爲前端或者用戶提供接口的時候,時常會遇到返回大量數據信息的情況,比如:有1000條用戶信息,有1000條新聞文章,有1000條商品信息等等。但是我們不可能將所有數據從數據庫獲取後一股腦的全部返回,這樣相當不好,會增大服務器壓力,同時也會增加前端渲染壓力,也不方便前端或者用戶使用。

這種情況下,我們就需要用到分頁處理。顧名思義,就是將大量數據進行分頁,每頁只有少量數據,在用戶希望通過接口獲取數據時,只需要在url中加入指定的參數,就可以獲取指定頁的數據,使用相當方便。

在Django中,我們通常使用django-rest-framework這個插件進行分頁,它提供了三種分頁器PageNumber分頁(普通分頁)、LimitOffset分頁(偏移分頁)、Cursor分頁(加密分頁),我們可以根據實際情況選擇合適的分頁器,下面來依次介紹這三種分頁器。

一、PageNumber分頁

class TestApi1(APIView):
    """PageNumber分頁"""
    def get(self, request):
        page = PageNumberPagination()  # 創建普通分頁器對象
        page.page_size = 3  # 設置每頁數據條數
        articles = Articles.get_articles()  # 獲取所有文章數據
        ret_page = page.paginate_queryset(articles, request, self)  # 用實例化的分頁器對所有數據進行分頁,並且返回當前頁的數據的列表
        articles_serializer = ArticlesSerializers(ret_page, many=True)  # 將當前頁數據序列化
        data = {
            'count': articles.count(),  # 獲取數據總數
            'previous': page.get_previous_link(),  # 獲取上一頁鏈接,如果沒有則是None
            'next': page.get_next_link(),  # 獲取下一頁鏈接,如果沒有則是None
            'results': articles_serializer.data,  # 當前頁的序列化數據
        }
        return Response(data, status=200)

在調用接口時,需要添加page參數,表示獲取哪一頁,如果沒有使用該參數,默認獲取第一頁,如果傳入不存在的頁數,則會返回404。

我這裏的本地的api是:http://127.0.0.1:8000/api/v1/blog/test1,沒有加參數表示獲取第一頁

觀察數據,的確是我想要的格式,這樣就可以了。再加入page參數試試:

二、LimitOffset分頁

class TestApi2(APIView):
    """LimitOffset分頁"""
    def get(self, request):
        page = LimitOffsetPagination()  # 創建偏移分頁器對象
        page.page_size = 3  # 設置每頁數據默認條數,在api中可以通過limit參數修改
        articles = Articles.get_articles()  # 獲取所有文章數據
        ret_page = page.paginate_queryset(articles, request, self)  # 用實例化的分頁器對所有數據進行分頁,並且返回當前頁的數據的列表
        articles_serializer = ArticlesSerializers(ret_page, many=True)  # 將當前頁數據序列化
        data = {
            'count': articles.count(),  # 獲取數據總數
            'previous': page.get_previous_link(),  # 獲取上一頁鏈接,如果沒有則是None
            'next': page.get_next_link(),  # 獲取下一頁鏈接,如果沒有則是None
            'results': articles_serializer.data,  # 當前頁的序列化數據
        }
        return Response(data, status=200)

調用接口時,需要傳入兩個參數:offset、limit,其中,offset表示偏移量,即若offset=0,則從第一條數據算起,若offset=6,則從第七條數據開始算起,limit表示往後偏移多少,如:offset=2&limit=5表示從第3條數據是算起之後的第5條。若不傳參數默認獲取第一頁。

三、Cursor分頁

Cursor分頁(加密分頁)和以上兩種分頁不太一樣,它不能通過自由的傳參來獲取指定的頁面,只能通過返回給你的上一頁下一頁的url來實現一頁一頁的跳轉。其中還需要注意,Cursor分頁默認會用created這個字段來排序,如果你的數據表中沒有該字段,則可以使用分頁器的ordering屬性來自定義排序字段。

class TestApi3(APIView):
    """Cursor分頁"""
    def get(self, request):
        page = CursorPagination()  # 創建加密分頁器對象
        page.ordering = '-id'  # 設置排序字段,按照id降序排列
        page.page_size = 3  # 設置每頁數據條數
        articles = Articles.get_articles()  # 獲取所有文章數據
        ret_page = page.paginate_queryset(articles, request, self)  # 用實例化的分頁器對所有數據進行分頁,並且返回當前頁的數據的列表
        articles_serializer = ArticlesSerializers(ret_page, many=True)  # 將當前頁數據序列化
        data = {
            'count': articles.count(),  # 獲取數據總數
            'previous': page.get_previous_link(),  # 獲取上一頁鏈接,如果沒有則是None
            'next': page.get_next_link(),  # 獲取下一頁鏈接,如果沒有則是None
            'results': articles_serializer.data,  # 當前頁的序列化數據
        }
        return Response(data, status=200)

第一步只能獲取第一頁:

這時可以看到我們獲取到了加密後的下一頁的url,我們可以通過請求這個url來獲取下一頁的數據。


通過以上描述,我們可以看到,我們每一個視圖我們都需要去實例化一個分頁器,然後去修改分頁器的一些屬性值來達到我們希望看到的效果,另外爲了讓數據清洗明瞭,我們每一次都還要單獨去定義一個data,來聲明返回數據的格式,雖然也不是很繁瑣,但是如果太多的話也不太好。

在django-rest-framework中,使用通用視圖視圖集時是能夠自動執行分頁的。我們需要在配置文件中進行設置。

實現PageNumber分頁(以通用視圖ListAPIView爲例)

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 3,
}
class TestApi4(ListAPIView):
    """PageNumber分頁"""
    queryset = Articles.get_articles()
    serializer_class = ArticlesSerializers

看,數據格式已經爲我們定義好了,相當方便。

實現LimitOffset分頁(以通用視圖ListAPIView爲例)

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 3,
}
class TestApi5(ListAPIView):
    """LimitOffset分頁"""
    queryset = Articles.get_articles()
    serializer_class = ArticlesSerializers

 

實現Cursor分頁(以通用視圖ListAPIView爲例)

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
    'PAGE_SIZE': 3,
}
class TestApi6(ListAPIView):
    """Cursor分頁"""
    queryset = Articles.get_articles()
    serializer_class = ArticlesSerializers
    pagination_class = CursorPagination
    pagination_class.ordering = '-id'

以上就是django-rest-framework分頁功能的基本實現,一般都是夠用的,如果需要有一些個性化的配置等等,可以參考官方文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章