過濾Filtering
對于列表數據可能需要根據字段進行過濾,我們可以通過添加django-fitlter擴展來增強支持。
pip install django-filter
在配置文件中增加過濾器類的全局設置:
"""drf配置信息必須全部寫在REST_FRAMEWORK配置項中"""
REST_FRAMEWORK = {# ....代碼省略。。。# 過濾查詢,全局配置'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}
在視圖類中添加類屬性filter_fields,指定可以過濾的字段
class Hom4APIView(ModelViewSet):queryset = Student.objects.all()serializer_class = StudentModelSerializerfilter_fields = ["sex","classmate"]# list方法中進行調用->調用了GenericAPIView中聲明的filter_queryset方法---> 配置中的過濾器類的filter_queryset---> filter_fields# 單個字段過濾
# http://127.0.0.1:8000/opt/s4/?classmate=502&sex=2
# http://127.0.0.1:8000/opt/s4/?sex=2
# 多個字段過濾
# http://127.0.0.1:8000/opt/s4/?classmate=502&sex=2
路由代碼:
from django.urls import path,include
from . import viewsfrom rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register("s2", views.Hom2APIView, "s2")
router.register("s4", views.Hom4APIView, "s4")urlpatterns = [path("s1/", views.HomeAPIView.as_view()),path("", include(router.urls)), # 等價于 urlpatterns += router.urlspath("s3/", views.Hom3APIView.as_view()),path("s3/", views.Hom3APIView.as_view()),
]
局部設置,直接在視圖中,指定當前視圖類中調用的過濾器類
# 先注釋掉settings中的全局過濾配置
from rest_framework.viewsets import ModelViewSet
from students.models import Student
from students.serializers import StudentModelSerializer
# Create your views here.
from django_filters.rest_framework import DjangoFilterBackend
class Hom4APIView(ModelViewSet):queryset = Student.objects.all()serializer_class = StudentModelSerializerfilter_backends = [DjangoFilterBackend, ]filter_fields = ["sex","classmate"]# list方法中進行調用->調用了GenericAPIView中聲明的filter_queryset方法---> 配置中的過濾器類的filter_queryset---> filter_fields
排序Ordering
對于列表數據,REST framework提供了OrderingFilter過濾器來幫助我們快速指明數據按照指定字段進行排序。
使用方法:
在類視圖中設置filter_backends,使用rest_framework.filters.OrderingFilter
過濾器,REST framework會在請求的查詢字符串參數中檢查是否包含了ordering參數,如果包含了ordering參數,則按照ordering參數指明的排序字段對數據集進行排序。
前端可以傳遞的ordering參數的可選字段值需要在ordering_fields中指明。
配置文件,settings.py,代碼:
"""drf配置信息必須全部寫在REST_FRAMEWORK配置項中"""
REST_FRAMEWORK = {# 。。。代碼省略# 過濾查詢,全局配置# 過濾和排序使用了一個公用的配置項,所以2個組件要么一起全局配置,要么就一起局部配置'DEFAULT_FILTER_BACKENDS': [# 'django_filters.rest_framework.DjangoFilterBackend', # 過濾'rest_framework.filters.OrderingFilter', # 排序],
}
視圖代碼:
from rest_framework.viewsets import ModelViewSet
from students.models import Student
from students.serializers import StudentModelSerializer
# Create your views here.
from django_filters.rest_framework import DjangoFilterBackend
class Hom4APIView(ModelViewSet):queryset = Student.objects.all()serializer_class = StudentModelSerializer# 局部過濾# filter_backends = [DjangoFilterBackend, OrderingFilter]# 過濾字段# filter_fields = ["sex","classmate"]# 數據排序ordering_fields = ['id', 'age']# 127.0.0.1:8000/books/?ordering=-age
# -id 表示針對id字段進行倒序排序
# id 表示針對id字段進行升序排序
上面提到,因為過濾和排序公用了一個配置項,所以排序和過濾要一起使用,則必須整個項目,要么一起全局過濾排序,要么一起局部過濾排序。
from rest_framework.viewsets import ModelViewSet
from students.models import Student
from students.serializers import StudentModelSerializer
# Create your views here.
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
class Hom4APIView(ModelViewSet):queryset = Student.objects.all()serializer_class = StudentModelSerializer# 局部過濾filter_backends = [DjangoFilterBackend, OrderingFilter]# 過濾字段filter_fields = ["sex","classmate"]# list方法中進行調用->調用了GenericAPIView中聲明的filter_queryset方法---> 配置中的過濾器類的filter_queryset---> filter_fields# 數據排序ordering_fields = ['id', 'age']
分頁Pagination
因為django默認提供的分頁器主要使用于前后端不分離的業務場景,所以REST framework也提供了分頁的支持。
我們可以在配置文件中設置全局的分頁方式,如:
REST_FRAMEWORK = {# 分頁,全局配置# 頁碼分頁器, ?page=頁碼&page_size=單頁數據量# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',# 偏移量分頁器, ?limit=單頁數據量&offset=數據開始下標'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination','PAGE_SIZE': 10 # 每頁數目,如果不設置,則沒有進行分配
}
# 如果在settings.py配置文件中, 設置了全局分頁,那么在drf中凡是調用了ListModelMixin的list(),都會自動分頁。如果項目中出現大量需要分頁的數據,只有少數部分的不需要分頁,則可以在少部分的視圖類中關閉分頁功能。
# 另外,視圖類在使用過分頁以后,務必在編寫queryset屬性時,模型.objects后面調用結果。例如:
# Student.objects.all()
class Hom5APIView(ListAPIView):pagination_class = None
也可通過自定義Pagination類,來為視圖添加不同分頁行為。在視圖中通過pagination_clas
屬性來指明。
可選分頁器
1) PageNumberPagination
前端訪問網址形式:
GET http://127.0.0.1:8000/students/?page=4
可以在子類中定義的屬性:
- page_size 每頁數目
- page_query_param 前端發送的頁數關鍵字名,默認為"page"
- page_size_query_param 前端發送的每頁數目關鍵字名,默認為None
- max_page_size 前端最多能設置的每頁數量
分頁器類,paginations
,代碼:
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
# PageNumberPagination,以頁碼作為分頁條件
# page=1&page_size=10 第1頁
# page=2&page_size=10 第2頁
# ...
# LimitOffsetPagination,以數據庫查詢的limit和offset數值作為分頁條件
# limit=10&offset=0 第1頁
# limit=10&offset=10 第2頁
# ...# 自定義分頁器,PageNumberPagination
class StudentPageNumberPagination(PageNumberPagination):page_query_param = "page" # 查詢字符串中代表頁碼的變量名page_size_query_param = "size" # 查詢字符串中代表每一頁數據的變量名page_size = 2 # 每一頁的數據量max_page_size = 4 # 允許客戶端通過查詢字符串調整的最大單頁數據量
視圖,views
,代碼:
from rest_framework.pagination import LimitOffsetPagination, PageNumberPagination# 分頁類往往會單獨的保存到一個獨立的模塊,例如:當前子應用目錄下創建一個pagination.py保存,使用時導包
class Hom5PageNumberPagination(PageNumberPagination):page_size = 10 # 默認分頁的每一頁數據量max_page_size = 20 # 設置允許客戶端通過地址欄參數調整的最大單頁數據量page_query_param = "pn" # 地址欄上代表頁碼的變量名,默認是 pagepage_size_query_param = "size" # 地址欄上代表單頁數據量的變量名,默認是page_sizeclass Hom5APIView(ModelViewSet):# queryset = Student.objects # 這句話在沒有進行分頁時不會報錯,調用了分頁則會報錯!queryset = Student.objects.all()serializer_class = StudentModelSerializer# 局部分頁# pagination_class = None # 關閉分頁功能# 局部分頁往往采用自定義分頁類,進行分頁數據量的配置pagination_class = Hom5PageNumberPaginationdef list(self, request, *args, **kwargs):# 獲取django的配置項from django.conf import settings# 獲取rest_framework的配置項# from rest_framework.settings import api_settings# print(api_settings.DEFAULT_PAGINATION_CLASS)return super().list(request, *args, **kwargs)
2)LimitOffsetPagination
前端訪問網址形式:
GET http://127.0.0.1/four/students/?limit=100&offset=100
可以在子類中定義的屬性:
- default_limit 默認限制,默認值與
PAGE_SIZE
設置一直 - limit_query_param limit參數名,默認’limit’
- offset_query_param offset參數名,默認’offset’
- max_limit 最大limit限制,默認None
分頁類,代碼:
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
# PageNumberPagination,以頁碼作為分頁條件
# page=1&size=10 第1頁
# page=2&size=10 第2頁
# LimitOffsetPagination,以數據庫查詢的limit和offset數值作為分頁條件
# limit=10&offset=0 第1頁
# limit=10&offset=10 第2頁# LimitOffsetPagination
class StudentLimitOffsetPagination(LimitOffsetPagination):limit_query_param = "limit" # 查詢字符串中代表每一頁數據的變量名offset_query_param = "offset" # 查詢字符串中代表頁碼的變量名default_limit = 2 # 每一頁的數據量max_limit = 4 # 允許客戶端通過查詢字符串調整的最大單頁數據量
視圖,views
,代碼:
from .paginations import StudentPageNumberPagination,StudentLimitOffsetPagination
class Student3ModelViewSet(ModelViewSet):queryset = Student.objects.all()serializer_class = StudentModelSerializer# 取消當前視圖類的分頁效果# pagination_class = None# 局部分頁pagination_class = StudentLimitOffsetPagination