drf 過濾器(條件查詢 排序 )分頁器
目錄
一、群查接口各種篩選組件
數據准備
models.py
View Code
admin.py 注冊
admin.site.register(models.Car)
serializers.py
class CarModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Car
fields = ['name', 'price', 'brand']
views.py
# Car的群查接口
from rest_framework.generics import ListAPIView
class CarListAPIView(ListAPIView):
queryset = models.Car.objects.all()
serializer_class = serializers.CarModelSerializer
urls.py
url(r'^cars/$', views.CarListAPIView.as_view()),
1.drf 搜索 過濾組件
views.py
from rest_framework.generics import ListAPIView
# 第一步:drf的SearchFilter - 搜索過濾
from rest_framework.filters import SearchFilter
class CarListAPIView(ListAPIView):
queryset = models.Car.objects # 固定的兩個東西,源碼內部默認為None
serializer_class = serializers.CarModelSerializer
# 第二步:局部配置 過濾類 們(全局配置用DEFAULT_FILTER_BACKENDS)
filter_backends = [SearchFilter]
# 第三步:SearchFilter過濾類依賴的過濾條件 => 接口:/cars/?search=...
search_fields = ['name', 'price']
# eg:/cars/?search=1,name和price中包含1的數據都會被查詢出
2. drf 排序 過濾組件
views.py
from rest_framework.generics import ListAPIView
# 第一步:drf的OrderingFilter - 排序過濾
from rest_framework.filters import OrderingFilter
class CarListAPIView(ListAPIView):
queryset = models.Car.objects
serializer_class = serializers.CarModelSerializer
# 第二步:局部配置 過濾類 們(全局配置用DEFAULT_FILTER_BACKENDS)
filter_backends = [OrderingFilter]
# 第三步:OrderingFilter過濾類依賴的過濾條件 => 接口:/cars/?ordering=...
ordering_fields = ['pk', 'price']
# eg:/cars/?ordering=-price,pk,先按price降序,如果出現price相同,再按pk升序
3. drf 基礎分頁組件
api / pahenations.py
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
# ?page=1,這個就是url中的key,
page_query_param = 'page'
# ?page=1 不傳自定義條數時默認一頁顯示的條數,可以通過下面的參數設置自定義
page_size = 3
# ?page=2&page_size=3 第二頁每頁顯示3條數據 用戶自定義一頁顯示的條數
page_size_query_param = 'page_size'
# 用戶自定義一頁顯示的條數最大限制:數值超過5也只顯示5條
max_page_size = 5
views.py
from rest_framework.generics import ListAPIView
class CarListAPIView(ListAPIView):
# 如果queryset沒有過濾條件,就必須 .all(),不然分頁會出問題,上面搜索和排序不需要all是因為人家已經過濾過了
queryset = models.Car.objects.all()
serializer_class = serializers.CarModelSerializer
# 分頁組件 - 給視圖類配置分頁類即可 - 分頁類需要自定義,繼承drf提供的分頁類即可
pagination_class = pagenations.MyPageNumberPagination
4. drf 偏移分頁組件
pahenations.py
from rest_framework.pagination import LimitOffsetPagination
class MyLimitOffsetPagination(LimitOffsetPagination):
# ?offset=從頭偏移的條數&limit=要顯示的條數
limit_query_param = 'limit'
offset_query_param = 'offset'
# ?不傳offset和limit默認顯示前3條,只設置offset就是從偏移位往后再顯示3條
default_limit = 3
# ?limit可以自定義一頁顯示的最大條數
max_limit = 5
# 在偏移組件基礎上只使用limit結合ordering可以實現排行前幾或后幾,后面我們會自定義limit過濾器就不需要基於分頁了
# ?ordering=-price&limit=2 => 價格前2
views.py
from rest_framework.generics import ListAPIView
class CarListAPIView(ListAPIView):
# 如果queryset沒有過濾條件,就必須 .all(),不然分頁會出問題
queryset = models.Car.objects.all()
serializer_class = serializers.CarModelSerializer
# 分頁組件 - 給視圖類配置分頁類即可 - 分頁類需要自定義,繼承drf提供的分頁類即可
pagination_class = pagenations.MyLimitOffsetPagination
5. drf游標分頁組件(了解)
pahenations.py
# 注:必須基於排序規則下進行分頁
# 1)如果接口配置了OrderingFilter過濾器,那么url中必須傳ordering
# 1)如果接口沒有配置OrderingFilter過濾器,一定要在分頁類中聲明ordering按某個字段進行默認排序
from rest_framework.pagination import CursorPagination
class MyCursorPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 3
page_size_query_param = 'page_size'
max_page_size = 5
ordering = '-pk' # 按照pk降序排列
views.py
from rest_framework.generics import ListAPIView
class CarListAPIView(ListAPIView):
# 如果queryset沒有過濾條件,就必須 .all(),不然分頁會出問題
queryset = models.Car.objects.all()
serializer_class = serializers.CarModelSerializer
# 分頁組件 - 給視圖類配置分頁類即可 - 分頁類需要自定義,繼承drf提供的分頁類即可
pagination_class = pagenations.MyCursorPagination
6. 自定義 limit 過濾器
我不想借助分頁,我就想自定義一個條數過濾器,他可以對各過濾組件過濾結果進行顯示限制
filters.py
# 自定義過濾器,接口:?limit=顯示的條數
class LimitFilter:
def filter_queryset(self, request, queryset, view):
# 前台固定用 ?limit=... 傳遞過濾參數
limit = request.query_params.get('limit')
if limit:
limit = int(limit)
return queryset[:limit] # 切片,限制條數
return queryset
# eg:/cars/?ordering=-price,pk&limit=3,先按price降序,如果出現price相同,再按pk升序,篩選結果顯示3條
views.py
from rest_framework.generics import ListAPIView
class CarListAPIView(ListAPIView):
# 如果queryset沒有過濾條件,就必須 .all(),不然分頁會出問題
queryset = models.Car.objects.all()
serializer_class = serializers.CarModelSerializer
# 局部配置 過濾類 們(全局配置用DEFAULT_FILTER_BACKENDS)
filter_backends = [LimitFilter]
7. 過濾器插件:django-filter
安裝
>: pip3 install django-filter
過濾條件層:自定義api/filters.py
# django-filter插件過濾器類
from django_filters.rest_framework.filterset import FilterSet
from . import models
# 自定義過濾字段
from django_filters import filters
class CarFilterSet(FilterSet):
min_price = filters.NumberFilter(field_name='price', lookup_expr='gte') # gte lte 源碼里面有,表示最大最小值
max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
class Meta:
model = models.Car
fields = ['brand', 'min_price', 'max_price']
# brand是model中存在的字段,一般都是可以用於分組的字段
# min_price、max_price是自定義字段,需要自己自定義過濾條件
視圖層:views.py
# django-filter插件過濾器
from django_filters.rest_framework import DjangoFilterBackend
from .filters import CarFilterSet
class CarListAPIView(ListAPIView):
queryset = models.Car.objects.all()
serializer_class = serializers.CarModelSerializer
# 局部配置 過濾類 們(全局配置用DEFAULT_FILTER_BACKENDS)
filter_backends = [DjangoFilterBackend]
# django-filter過濾器插件使用
filter_class = CarFilterSet
# 接口:?brand=...&min_price=...&max_price=...
# eg:?brand=寶馬&min_price=5&max_price=10 => 5~10間的寶馬牌汽車