<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          DRF框架三種分頁功能的實現(xiàn) - 在DjangoStarter項目模板中封裝

          共 3713字,需瀏覽 8分鐘

           ·

          2022-04-17 01:56

          前言

          繼續(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ù),pagepage_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


          文章推薦:


          瀏覽 67
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久黄色大片 | 台湾无码中文网 | 成人视频一区二区 | 永久免费不卡在线观看黄网站 | 在线精品国产视频观看 |