Django REST Framework 学习笔记(十四):过滤器组件

  • Title(EN): Django REST Framework Learning Notes (14): Filters
  • Author: dog2

基本信息

  • 源码 rest_framework.filters
  • 官方文档
    • DRF API Guild - Filtering
    • django-filter
  • 本文demo代码Github

DRF过滤组件

DRF搜索过滤组件

urls.py

1
2
3
4
5
6
7
from django.urls import path

from . import views

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

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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

1
2
3
4
5
6
7
from django.urls import path

from . import views

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

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
# 第一步: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

1
2
3
4
5
6
7
from django.urls import path

from . import views

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

filters.py

1
2
3
4
5
6
7
8
9
10
11
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

1
2
3
4
5
6
7
8
9
10
# 自定义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

1
2
3
4
5
6
7
from django.urls import path

from . import views

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

filters.py

1
2
3
4
5
6
7
8
9
10
11
12
13
# django-fitler插件:自定义过滤字段
from django_filters import filters
from django_filters.rest_framework.filterset import FilterSet

class CarFilterSet(FilterSet):
min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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间的宝马牌汽车

扩展阅读

  • drf 过滤器组件与自定义过滤器