1. 程式人生 > 其它 >drf : 過濾 排序 分頁

drf : 過濾 排序 分頁

目錄

過濾和排序

並不是所有的介面都需要寫,查詢所有才需要過濾(根據條件過濾),排序(按某個規則排序,也可倒序)。

匯入模組:

"""
OrderingFilter : 排序
SearchFilter : 過濾
"""
from rest_framework.filters import OrderingFilter,SearchFilter

過濾,內建的過濾,必須繼承GenericAPIView,才會有這個類屬性。

作用:模糊匹配原則,查詢關鍵字只能為search

views.py

from rest_framework.filters import SearchFilter
class BookAPIView(ViewSetMixin,ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    # 在檢視類中配置,最頂層至少是GenericAPIView,GenericAPIView中有filter_backends
    filter_backends = [SearchFilter,]
    # 過濾條件:按自釘子欄位過濾
    search_fields = ['price']

排序

view.py

from rest_framework.filters import OrderingFilter
class BookAPIView(ViewSetMixin,ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    # 在檢視類中配置,最頂層至少是GenericAPIView,GenericAPIView中有filter_backends
    filter_backends = [OrderingFilter]
    # 按照那個欄位排序
    ordering_fields = ['id']

過濾和排序組合

views.py

"""
OrderingFilter : 排序
SearchFilter : 過濾
"""
from rest_framework.filters import OrderingFilter,SearchFilter
class BookAPIView(ViewSetMixin,ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    # 在檢視類中配置,最頂層至少是GenericAPIView,GenericAPIView中有filter_backends
    filter_backends = [SearchFilter,OrderingFilter]
    # 過濾條件:按名字過濾
    search_fields = ['name']
    # 按照那個欄位排序
    ordering_fields = ['id']
    # 排序可以多個條件排序,前提第一個條件要一直
    ordering_fields = ['id','price']

按照name欄位(西)過濾,按到id欄位倒序過濾,正序不用加-。

如果多個條件排序: http://127.0.0.1:8000/books/?ordering=-id,100

第三方過濾

作用:只能精準匹配,查詢字為欄位名。

安裝:

pip install django-filter

匯入模組:

from django_filters.rest_framework import DjangoFilterBackend

註冊:

INSTALLED_APPS = [
    'django_filters'
]

views.py,檢視層

from django_filters.rest_framework import DjangoFilterBackend


class BookAPIView(ViewSetMixin, ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    filter_backends = [DjangoFilterBackend, ]
    # 過濾條件:按名字過濾
    filterset_fields = ['name']
    # 按照那個欄位排序
    ordering_fields = ['id']

第三方過濾查詢多個

自定義過濾器

作用:模糊匹配與精準匹配,查詢關鍵字為欄位名。

開設一個filter.py檔案。

from rest_framework.filters import BaseFilterBackend


class MyFilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # <rest_framework.request.Request: GET '/books/?name=%E8%A5%BF'>
        print(request)
        """
        過濾前的資料
        <QuerySet 
        [<Books: Books object (1)>, 
        <Books: Books object (2)>, 
        <Books: Books object (3)>, 
        <Books: Books object (4)>, 
        <Books: Books object (5)>]>
        """
        print(queryset)
        query = request.query_params.get('name')

        if query:
            # 西
            print(query)
            queryset = queryset.filter(name__contains=query)
            """
            過濾後的資料。
            <QuerySet 
            [<Books: Books object (1)>, 
            <Books: Books object (2)>, 
            <Books: Books object (3)>]>
            """
            print(queryset)
        return queryset

views.py

from .filter import MyFilter


# 自定義過濾
class BookAPIView(ViewSetMixin, ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    filter_backends = [MyFilter, ]

分頁

首先:在五個介面中,只有查詢所有才涉及到分頁。

預設提供三種分頁方式:

  • PageNumberPagination
  • LimitOffsetPagination
  • CursorPagination

匯入模組

from rest_framework.pagination import PageNumberPagination,CursorPagination,LimitOffsetPagination

基本分頁,使用頻率高:PageNumberPagination

匯入模組:

from rest_framework.pagination import PageNumberPagination

需要重寫PageNumberPagination中的四個類方法。

page.py

from rest_framework.pagination import PageNumberPagination, CursorPagination, LimitOffsetPagination


class MyPageNumberPagination(PageNumberPagination):
    # 每頁顯示條數
    page_size = 3
	  # 查詢條件為page --> ?page=頁數
    page_query_param = 'page'  
		 # 每頁顯示的條數的查詢條件,?page=3&size=9 查詢第三頁,第三頁顯示9條
    page_size_query_param = 'size' 
		# 控制每頁上限資料為幾條
    max_page_size = 5 

views.py

from rest_framework.generics import ListAPIView
from rest_framework.viewsets import ViewSetMixin
from .filter import MyFilter
from .page import MyPageNumberPagination

# 自定義過濾
class BookAPIView(ViewSetMixin, ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    filter_backends = [MyFilter, ]
    # 分頁只要一種方式,必須繼承GenericAPIView類
    pagination_class = MyPageNumberPagination

舉例:

偏移分頁: LimitOffsetPagination

匯入模組:

from rest_framework.pagination import LimitOffsetPagination

page.py

class MyLimitOffsetPagination(LimitOffsetPagination):
    # 預設每頁顯示資料為幾條
    default_limit = 3
    # 當前頁獲取幾條資料: ?limit=3 , 如果沒有寫使用預設 default_limit
    limit_query_param = 'limit'
    # ?limit=3&offset=2 從第二條資料開始但不包括第二條資料向下展示三條。
    offset_query_param = 'offset'
    # 最大顯示條數
    max_limit = 5

views.py

from rest_framework.generics import ListAPIView
from rest_framework.viewsets import ViewSetMixin
from .filter import MyFilter
from .page import MyPageNumberPagination,MyLimitOffsetPagination

# 自定義過濾
class BookAPIView(ViewSetMixin, ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    filter_backends = [MyFilter, ]
    # 分頁只要一種方式,必須繼承GenericAPIView類
    pagination_class = MyLimitOffsetPagination

CursorPagination,一般用作體量非常大或者手機端的查詢。

作用:只能選擇上一頁和下一頁,不能指定某一頁,但是查詢速度快。大資料量和app分頁不需要指定指定跳轉到第幾頁,下拉載入下一頁即可。

page.py

from rest_framework.pagination import CursorPagination


class MyCursorPagination(CursorPagination):
    # 預設每頁顯示條數
    page_size = 3
    # 查詢關鍵字?cursor=cD0z
    cursor_query_param = 'cursor'
    # 排序,正向或者倒序
    ordering = 'id'

views.py

from rest_framework.generics import ListAPIView
from rest_framework.viewsets import ViewSetMixin
from .filter import MyFilter
from .page import MyCursorPagination

class BookAPIView(ViewSetMixin, ListAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializers
    filter_backends = [MyFilter, ]
    # 分頁只要一種方式,必須繼承GenericAPIView類
    pagination_class = MyCursorPagination

總結:PageNumberPagination,LimitOffsetPagination,CursorPagination。三者區別。

PageNumberPagination,LimitOffsetPagination: 可以從中間位置獲取到某一頁,CursorPagination分頁只能獲取上一頁和下一頁。

PageNumberPagination,LimitOffsetPagination:獲取到某一頁時,需要從開始過濾到要取的頁面數的資料。CursorPagination在取到某一頁時不用過濾之前的資料。