一、使用drf过滤器
-
drf过滤器:在GenericAPIView这个视图基类的
def filter_queryset(self, queryset)方法中,通过self.filter_backends的配置来拿到过滤器并使用。但drf 默认在settings文件中的配置是空,既不使用过滤器。 -
drf默认为我们提供了两个过滤器类
-
class OrderingFilter(BaseFilterBackend)用于排序使用时: 在url添加配置中参与排序的字段
-
class SearchFilter(BaseFilterBackend)用于搜索使用时: 在url添加配置中参与搜索的字段
-
-
如果我们要使用过滤器也可以通过局部配置和全局配置来进行使用
局部配置:
from rest_framework.generics import ListAPIView
# OrderingFilter排序、SearchFilter搜索
from rest_framework.filters import OrderingFilter, SearchFilter
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置过滤器类
filter_backends = [OrderingFilter, SearchFilter]
# 参与排序的字段: ordering=-price,id,students
ordering_fields = [\'price\', \'id\', \'students\']
# 参与搜索的字段: search=python (name字段中带python就ok)
search_fields = [\'name\', \'brief\']
# 携带排序的过滤参数的url: http://127.0.0.1:8000/course/free?ordering=-price 降序
# 携带搜索的过滤参数的url: http://127.0.0.1:8000/course/free?search=python (name字段中带python就ok)
二、自定义过滤器
-
自定义过滤器类。继承
BaseFilterBackend类(实际上看过源码你就知道继不继承都可以,因为BaseFilterBackend类并没有做什么实质性的事情) - 实现def filter_queryset(self, request, queryset, view) 方法,必须返回一个queryset对象
自定义过滤器类
from rest_framework.filters import BaseFilterBackend
# 自定义过滤器类
class LimitFilter(BaseFilterBackend):
# 必须实现filter_queryset方法,返回queryset对象
def filter_queryset(self, request, queryset, view):
# 取出过滤条件
limit = request.query_params.get("limit") # 过滤参数
try:
return queryset[:int(limit)]
except:
return queryset
使用自定义过滤器类
from . import filters
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置过滤器类
filter_backends = [filters.LimitFilter]
# 携带自定义过滤字段参数的url: http://127.0.0.1:8000/course/free?limit=1
三、使用django-filter模块
django-filter模块可以做一些更高级的过滤,也可以自定义过滤,比如分类筛选、筛选区间等
安装依赖: pip install django-filter
django-filter模块为django和drf都做了相应的支持。如果是drf做前后端分离的项目就使用from django_filters.rest_framework import DjangoFilterBackend
使用:
局部配置过滤器类:filter_backends = [DjangoFilterBackend]
参与分类筛选的字段:filter_fields = [\'course_category\'](看源码得知,其实源码中反射了2个字段名,分别是:filterset_fields、filter_fields,反射了两个类名,分别是:filterset_class、filter_class、)
# 分类筛选:django-filter:filter_backends配置DjangoFilterBackend,再在filter_fields中配置分组筛选的字段
from django_filters.rest_framework import DjangoFilterBackend
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置过滤器类
filter_backends = [DjangoFilterBackend]
# 参与分类筛选的字段:
filter_fields = [\'course_category\']
# 携带分类筛选字段的参数的url: http://127.0.0.1:8000/course/free?course_category=2
3.1 基于django-filter模块自定义过滤器类实现价格区间
- 自定义过滤器类。继承
from django_filters.rest_framework.filterset import FilterSet类 - 自定义分类筛选的字段。在Meta类中通过fields来指定筛选的字段。和定义序列化类方法一致
自定义过滤器类
# 基于django-filter插件,完成指定区间筛选(一般都是对应数字字段)
from django_filters.rest_framework.filterset import FilterSet
from django_filters import filters
from . import models
class CourseFilterSet(FilterSet):
# field_name:要过滤的数据库字段,lookup_expr:过滤条件
min_price = filters.NumberFilter(field_name=\'price\', lookup_expr=\'gte\') # 条件:大于price
max_price = filters.NumberFilter(field_name=\'price\', lookup_expr=\'lte\') # 条件:小于price
class Meta:
model = models.Course
# 参与分类筛选的字段:
fields = [\'course_category\', \'max_price\', \'min_price\']
使用自定义过滤器类
# 分类筛选:django-filter:filter_backends配置DjangoFilterBackend,再在filter_fields中配置分组筛选的字段
from django_filters.rest_framework import DjangoFilterBackend
# 自定义过滤器类
from . import filters
class FreeCourseListAPIView(ListAPIView):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).order_by(
"-orders").all()
serializer_class = serializers.FreeCourseModelSerializer
# 局部配置过滤器类
filter_backends = [DjangoFilterBackend]
# 使用基于django-filter自定义过滤器类
filter_class = filters.CourseFilterSet
# 携带分类筛选字段的参数的url: http://127.0.0.1:8000/course/free?min_price=20&max_price=80
自定义过滤器字段对照表
models.AutoField: {\'filter_class\': NumberFilter},
models.CharField: {\'filter_class\': CharFilter},
models.TextField: {\'filter_class\': CharFilter},
models.BooleanField: {\'filter_class\': BooleanFilter},
models.DateField: {\'filter_class\': DateFilter},
models.DateTimeField: {\'filter_class\': DateTimeFilter},
models.TimeField: {\'filter_class\': TimeFilter},
models.DurationField: {\'filter_class\': DurationFilter},
models.DecimalField: {\'filter_class\': NumberFilter},
models.SmallIntegerField: {\'filter_class\': NumberFilter},
models.IntegerField: {\'filter_class\': NumberFilter},
models.PositiveIntegerField: {\'filter_class\': NumberFilter},
models.PositiveSmallIntegerField: {\'filter_class\': NumberFilter},
models.FloatField: {\'filter_class\': NumberFilter},
models.NullBooleanField: {\'filter_class\': BooleanFilter},
models.SlugField: {\'filter_class\': CharFilter},
models.EmailField: {\'filter_class\': CharFilter},
models.FilePathField: {\'filter_class\': CharFilter},
models.URLField: {\'filter_class\': CharFilter},
models.GenericIPAddressField: {\'filter_class\': CharFilter},
models.CommaSeparatedIntegerField: {\'filter_class\': CharFilter},
models.UUIDField: {\'filter_class\': UUIDFilter},