Contents

DRF 过滤器组件

:::tip Django REST Framework. Filters :::

基本信息

源码

rest_framework.filters

官方文档

DRF API Guide-Filtering

django-filter

DRF 过滤组件

DRF 搜索过滤组件

urls.py

from django.urls import path

from . import views

urlpatterns = [
     path('cars/', views.CarListAPIView.as_view()),     # SearchFilter
]

views.py

# drf的SearchFilter
# 第一步: 搜索过滤
from rest_framework.filters import SearchFilter

class CarListAPIView(ListAPIView):
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer  #自定义认证

    # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
    filter_backends = [SearchFilter]

    # 第三步:SearchFilter过滤类依赖的过滤条件 => 接口:/cars/?search=...
    search_fields = ['name', 'price']  #筛选字段
    # eg:/cars/?search=1,name和price中包含1的数据都会被查询出

DRF 排序过滤组件

urls.py

from django.urls import path

from . import views

urlpatterns = [
     path('cars2/', views.CarListAPIView2.as_view()),   # OrderingFilter
]

views.py

# 第一步:drf的OrderingFilter - 排序过滤
from rest_framework.filters import OrderingFilter

class CarListAPIView2(ListAPIView):
    queryset = models.Car.objects.all()
    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升序

自定义过滤器

urls.py

from django.urls import path

from . import views

urlpatterns = [
     path('cars3/', views.CarListAPIView3.as_view()),   # 自定义fitler
]

filters.py

from . import models

# 自定义过滤器,接口:?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

views.py

# 自定义fitler
from .filters import LimitFilter

class CarListAPIView3(ListAPIView):
    # 如果queryset没有过滤条件,就必须 .all(),不然分页会出问题
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer

    # 局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
    filter_backends = [LimitFilter]

过滤器插件 django-filter

urls.py

from django.urls import path

from . import views

urlpatterns = [
     path('cars4/', views.CarListAPIView4.as_view()),   # 插件django-filter
]

filters.py

# django-fitler插件:自定义过滤字段
from django_filters import filters
from django_filters.rest_framework.filterset import FilterSet
from django.db.models import Q


class CarFilterSet(FilterSet):
    min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
    max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
    top_category = django_filters.NumberFilter(method='top_category_filter')


    def top_category_filter(self, queryset, name, value):
        return queryset.filter(Q(category_id=value)|Q(category__parent_category_id=value)|Q(category__parent_category__parent_category_id=value))


    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 CarListAPIView4(ListAPIView):
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer

    # 局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
    filter_backends = [DjangoFilterBackend]

    # django-filter过滤器插件使用
    #filter_class = CarFilterSet
    filterset_class = CarFilterSet  # 旧版写作filter_class, 新版写作fitlerset_class
    # 接口:?brand=...&min_price=...&max_price=...
    # eg:?brand=宝马&min_price=5&max_price=10 => 5~10间的宝马牌汽车