Django Rest Framework 源碼解讀( 六)分頁功能

這是我參與更文挑戰的第18天,活動詳情查看: 更文挑戰前端

1、分頁介紹

分頁有三種方式數據庫

  • 普通分頁,看第n頁,每頁顯示m條數據;
  • 切割分頁,在n個位置,向後查看m條數據;
  • 加密分頁,這與普通分頁方式類似,不過對url中的請求頁碼進行加密。

1 路由

1.1 主路由

from django.conf.urls import url, include
from django.urls import path

urlpatterns = [
    url(r'^api/', include('api.urls')),
]
複製代碼

1.2 app路由

from django.conf.urls import url, include, re_path
from api import views

urlpatterns = [
    re_path(r'^(?P<version>v\d)/users/$', views.UserView.as_view(), name='user'),
]
複製代碼

2 視圖

在不使用django rest framework中的分頁組件仍可以達到目的django

from rest_framework.views import APIView
from rest_framework import serializers
from api.models import UserInfo
from rest_framework.pagination import PageNumberPagination


class MyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo  # models類名
        # 方法一:生成全部數據庫字段
        fields = "__all__"


class UserView(APIView):
    def get(self, request, *args, **kwargs):
        # 1 獲取全部數據
        users = UserInfo.objects.all()
				ser = MyUserSerializer(instance=users, many=True)
				return HttpResponse(ser.data)
複製代碼

3 返回結果

2、PageNumberPagination

1 自定義分頁類

from rest_framework.pagination import PageNumberPagination

class MyPageNumberPagination(PageNumberPagination):
    page_size = 2
    max_page_size = 5
    page_size_query_param = 'size'
    page_query_param = 'page'
複製代碼
  • page_query_param:表示url中的頁碼參數
  • page_size_query_param:表示url中每頁數量參數
  • page_size:表示每頁的默認顯示數量
  • max_page_size:表示每頁最大顯示數量,作限制使用,避免忽然大量的查詢數據,數據庫崩潰

2 視圖

class PagerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Role
        fields = "__all__"

class MyPageNumberPagination(PageNumberPagination):
    page_size = 2
    page_size_query_param = "size"
    max_page_size = 5
    page_query_param = "page"

class UserView(APIView):
    def get(self, request, *args, **kwargs):
        # 1 獲取全部數據
        users = UserInfo.objects.all()
        # 2 建立分頁對象
        pg = MyPageNumberPagination()
        # 3 在數據庫獲取分頁數據
        users_info = pg.paginate_queryset(queryset=users, request=request, view=self)
        # 4 對數據進行序列化
        ser = MyUserSerializer(instance=users_info, many=True)
        # return Response(ser.data)
        return pg.get_paginated_response(ser.data)
複製代碼
  • 首先須要實例化咱們定義的分頁類
  • 而且對實例化類進行傳參控制
  • 最後將分頁後的對象做序列化

3 測試結果

3、LimitOffsetPagination

1 自定義分頁類

from rest_framework.pagination import LimitOffsetPagination

class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 5
複製代碼
  • default_limit:表示默認每頁顯示幾條數據
  • limit_query_param:表示url中本頁須要顯示數量參數
  • offset_query_param:表示從數據庫中的第幾條數據開始顯示參數
  • max_limit:表示每頁最大顯示數量,作限制使用,避免忽然大量的查詢數據,數據庫崩潰

2 視圖

class MyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo  # models類名
        # 方法一:生成全部數據庫字段
        fields = "__all__"

class MyPageNumberPagination(LimitOffsetPagination):
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 5

class UserView(APIView):
    def get(self, request, *args, **kwargs):
        # 1 獲取全部數據
        users = UserInfo.objects.all()
        # 2 建立分頁對象
        pg = MyPageNumberPagination()
        # 3 在數據庫獲取分頁數據
        users_info = pg.paginate_queryset(queryset=users, request=request, view=self)
        # 4 對數據進行序列化
        ser = MyUserSerializer(instance=users_info, many=True)
        # return Response(ser.data)
        return pg.get_paginated_response(ser.data)
複製代碼
  • 首先須要實例化咱們定義的分頁類
  • 而且對實例化類進行傳參控制
  • 最後將分頁後的對象做序列化

3 測試結果

4、使用加密分頁

若是使用普通分頁時,因爲向用戶提供了可選參數page,用戶能夠直接跳到數據分頁以後的任意頁碼。可是這樣作的後果就是,數據庫的負載變大,返回結果的效率緩慢。可是一旦使用加密以後,雖然提供可選參數cursor,可是對頁碼進行加密,用戶沒法知道當前頁,而是以上一頁下一頁的方式翻閱數據。有效避免了數據庫的負荷。可是就須要向用戶提供上一頁下一頁的urlapi

1 自定義分頁類

from rest_framework.pagination import LimitOffsetPagination

class MyCursorPagination(CursorPagination):
    ordering = 'id'
複製代碼
  • ordering:表示返回數據的排序方式

2 視圖

class MyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo  # models類名
        # 方法一:生成全部數據庫字段
        fields = "__all__"

class MyPageNumberPagination(CursorPagination):
    ordering = 'id'

class UserView(APIView):
    def get(self, request, *args, **kwargs):
        # 1 獲取全部數據
        users = UserInfo.objects.all()
        # 2 建立分頁對象
        pg = MyPageNumberPagination()
        # 3 在數據庫獲取分頁數據
        users_info = pg.paginate_queryset(queryset=users, request=request, view=self)
        # 4 對數據進行序列化
        ser = MyUserSerializer(instance=users_info, many=True)
        # return Response(ser.data)
        return pg.get_paginated_response(ser.data)
複製代碼
  • 首先須要實例化咱們定義的分頁類
  • 而且對實例化類進行傳參控制
  • 最後將分頁後的對象做序列化
  • 因爲要想用戶提供可用的上下頁接口,因此只能用pg.get_paginated_response(ser.data)作返回

3 測試結果

5、總結

三種分頁中,普通分頁與django中的分頁基本沒有區別。不過要作分頁返回給前端數據,就要從數據庫中取出數據,而後在作分頁序列化。若是用戶一下在前幾頁請求數據庫中的最後幾頁數據,對查詢數據庫的時延,對數據庫的負載較大,就會出現問題,這個時候就可使用加密分頁,限制用戶的訪問,只提供前一頁和後一頁的接口。markdown

相關文章
相關標籤/搜索