DRF框架三種分頁功能的實現(xiàn) - 在DjangoStarter項目模板中封裝
前言
繼續(xù)Django后端開發(fā)系列文章。剛好遇到一個分頁的需求,就記錄一下。
Django作為一個“全家桶”型的框架,本身啥都有,分頁組件也是有的,但默認的分頁組件沒有對API開發(fā)做優(yōu)化,所以DjangoRestFramework這個專門寫API的框架又把Django的分頁組件包裝了一層,集成在viewsets里的時候會更方便。
不過我們不可能一直用viewsets,有一部分API還是要用自由度更高的ApiView的,但ApiView里又沒辦法直接使用默認的分頁組件,這時我們就需要封裝一下。
并且DjangoRestFramework默認的分頁信息也不夠全,比如沒有總頁數(shù),這點我們也可以在封裝的時候魔改一下。
DRF中的分頁方式
DRF中為我們封裝了三種分頁方式,分別是:
PageNumberPagination:顧名思義,不解釋LimitOffsetPagination:Offset分頁CursorPagination:加密分頁
本文打算只介紹最常用的第一種,后面兩種同時也會做封裝,但篇幅關(guān)系就不介紹了,有興趣的同學可以嘗試使用一下。
開始代碼
首先還是在我們的「DjangoStarter」項目中,在utils目錄下新建一個名為paginator的Python Package。
因為代碼不多,我們直接寫在utils/paginator/__init__.py文件下就好。
from?collections?import?OrderedDict
from?django.core.paginator?import?Paginator
from?rest_framework.pagination?import?PageNumberPagination,?LimitOffsetPagination,?CursorPagination
from?rest_framework.response?import?Response
class?NumberPaginator(PageNumberPagination):
????"""頁碼分頁"""
????def?__init__(
????????????self,
????????????page_size,
????????????page_size_query_param='page_size',
????????????page_query_param='page',
????????????max_page_size=None
????):
????????"""
????????初始化分頁
????????:param?page_size:?每頁顯示多少條
????????:param?page_size_query_param:?URL中每頁顯示條數(shù)的參數(shù)
????????:param?page_query_param:?URL中頁碼的參數(shù)
????????:param?max_page_size:?最大頁碼數(shù)限制
????????"""
????????self.page_size?=?page_size
????????self.page_size_query_param?=?page_size_query_param
????????self.page_query_param?=?page_query_param
????????self.max_page_size?=?max_page_size
????def?get_paginated_response(self,?data):
????????paginator:?Paginator?=?self.page.paginator
????????return?Response(OrderedDict([
????????????('total_item_count',?paginator.count),
????????????('page_count',?paginator.num_pages),
????????????('page_number',?self.page.number),
????????????('page_size',?self.page_size),
????????????('next',?self.get_next_link()),
????????????('previous',?self.get_previous_link()),
????????????('results',?data)
????????]))
class?LimitOffsetPaginator(LimitOffsetPagination):
????"""Offset分頁"""
????default_limit?=?1
????limit_query_param?=?'limit'
????offset_query_param?=?'offset'
????max_limit?=?999
class?CursorPaginator(CursorPagination):
????"""加密分頁"""
????cursor_query_param?=?'cursor'
????page_size?=?1
????ordering?=?'-id'??#?重寫要排序的字段
針對前面說的“DjangoRestFramework默認的分頁信息也不夠全”問題,我重寫了get_paginated_response方法,在返回值中加入這幾個參數(shù)
page_count:總頁數(shù)page_number:當前頁碼page_size:每頁數(shù)量
然后另外兩個參數(shù)也改了名字,更直觀,更符合我們平時的開發(fā)習慣。
...
這樣就完成了封裝,我們接下來在代碼里測試一下
測試接口
來寫個測試接口看看效果
from?utils.paginator?import?NumberPaginator
@swagger_auto_schema(
????method='get',?operation_summary='測試分頁功能',
????manual_parameters=[
????????openapi.Parameter('page',?openapi.IN_QUERY,?type=openapi.TYPE_NUMBER),
????????openapi.Parameter('page_size',?openapi.IN_QUERY,?type=openapi.TYPE_NUMBER),
????])
@api_view()
def?test_page(request):
????#?測試數(shù)據(jù)
????data?=?[1,?2,?3,?4,?5,?6,?7,?8,?9,?10]
????paginator?=?NumberPaginator(request.query_params.get('page_size',?10))
????return?paginator.get_paginated_response({
????????'data':?paginator.paginate_queryset(queryset=data,?request=request)
????})
配置一下路由
urlpatterns?=?[
????path('test_page',?views.test_page),
]
測試效果
寫完的接口接受兩個參數(shù),page和page_size,我在@swagger_auto_schema裝飾器里聲明了這兩個參數(shù),方便我們在Swagger文檔中做測試。
我們設(shè)定page_size=5,拿到的JSON數(shù)據(jù)是這樣的:
{
??"message":?"請求成功",
??"code":?200,
??"data":?{
????"total_item_count":?10,
????"page_count":?2,
????"page_number":?1,
????"page_size":?"5",
????"next":?"http://127.0.0.1:8005/core/test_page?page=2&page_size=5",
????"previous":?null,
????"results":?{
??????"data":?[
????????1,
????????2,
????????3,
????????4,
????????5
??????]
????}
??}
}
效果不錯,很清晰。
收工。
參考資料
https://www.cnblogs.com/liwenzhou/p/9398959.html
文章推薦:
