REST framework 过滤组件 排序组件 django-filter

使用DRF的过滤组件, 排序组件 django-filter前提都是群查接口,并且使用的视图类都要直接或间接的继承GenericAPIView类

数据准备

  • models.py
class Car(models.Model):
    name = models.CharField(max_length=16, unique=True, verbose_name='车名')
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
    brand = models.CharField(max_length=16, verbose_name='品牌')
​
    class Meta:
        db_table = 'api_car'
        verbose_name = '汽车表'
        verbose_name_plural = verbose_name
​
    def __str__(self):
        return self.name
  • 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()),

SearchFilter 搜索过滤组件 

使用步骤:
1.导入搜索过滤器 

from rest_framework.filters import SearchFilter

2.局部配置

filter_backends = [SearchFilter]

3.局部配置过滤类依赖的过滤条件(字段)

search_fields = ['name', 'price']
注意:依赖的过滤字段只能配置序列化类中fields里配置的字段

接口使用样式:
/cars/?search=...
eg:/cars/?search=1,name和price中包含1的数据都会被查询出

案例:

  • views.py
from rest_framework.generics import ListAPIView
​
# 第一步: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的数据都会被查询出

OrderingFilter  排序过滤组件

使用步骤:
1.导入搜索过滤 

from rest_framework.filters import OrderingFilter

2.局部配置

filter_backends = [OrderingFilter]

3.局部配置过滤类依赖的过滤条件(字段)

ordering_fields = ['pk', 'price']

接口使用样式:
/cars/?ordering=...
eg:/cars/?ordering=-price,pk,先按price降序,如果出现price相同,再按pk升序

案例:

  • views.py
from rest_framework.generics import ListAPIView
​
# 第一步:drf的OrderingFilter - 排序过滤
from rest_framework.filters import OrderingFilter
​
class CarListAPIView(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升序

自定义过滤类

源码: GenericAPIView类中的filter_queryset方法调用过滤,排序组件

class GenericAPIView(views.APIView):
    ...
    # 配置过滤器路径
    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
    ...
    
    def filter_queryset(self, queryset):  # self是视图类对象
        # 若自己的视图列中配置了filter_backends=[过滤类] 就走视图类中的
        for backend in list(self.filter_backends):
            # 当时视图类中配置了filter_backends=[过滤类]
            # 下面这步会调用我们自己定义的过滤类的filter_queryset方法
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset

自定义步骤:

1.自定义过滤类,重写filter_queryset方法

2.在视图类中配置filter_backends = [自定义过滤类]

补充:
自定义过滤类不需要继承GenericAPIView,因为视图类继承了ListAPIView, ListAPIView本来就继承GenericAPIView
我们自定义的过滤类要在视图类中配置,当源码中的GenericAPIView要调用过滤类时就会调用我们在视图类中配置的自定义过滤类,从而调用filter_query方法

案例:

  • filters.py
class LimitFilter:
    # 重写filter_queryset方法
    def filter_queryset(self, request, queryset, view):
        # 从get请求中获取limit的值
        limit_mun = request.query_params.get('limit')
        if limit_mun:
            limit_mun = int(limit_mun)
            # 将queryset列表按limit_num切分
            return queryset[:limit_mun]
        return queryset
  • 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 = [OrderingFilter, SearchFilter, LimitFilter]

    search_fields = ['name', 'price']
    ordering_fields = ['pk', 'price']

    eg:/cars/?search=1?limit=5?ordering=-price,pk,
    name和price中包含1的数据都会被查询出,先按price降序,如果出现price相同,再按pk升序并且显示5条

django-filter 过滤器插件

安装

pip3 install django-filter

settings.py中配置

INSTALLED_APPS = [
    ...
    'django_filters',  # 需要注册应用,
]
全局配置
REST_FRAMEWORK = {
    ...
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

使用

  • filters.py
from django_filters.rest_framework.filterset import FilterSet
from . import models
from django_filters import filters
​
class CarFilterSet(FilterSet):
    # 自定义过滤字段
    max_price = filters.NumberFilter(
        field_name='price',  # 该自定义字段关联的model类表中的字段
        lookup_expr='gte',  # 查找的条件  'gte':大于等于
    )
    min_price = filters.NumberFilter(
        field_name='price',  # 该自定义字段关联的model类表中的字段
        lookup_expr='lte',  # 查找的条件  '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间的宝马牌汽车

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值