DRF的Filter组件

如果某个API需要传递一些条件进行搜索,其实就在是URL后面通过GET传参即可,例如:

/api/users?age=19&category=12

在drf中filter组件可以支持条件搜索。

1. 自定义filter

# models.py
from django.db import models class Role(models.Model):
""" 角色表 """
title = models.CharField(verbose_name='名称', max_length=32) class Department(models.Model):
""" 部门表 """
title = models.CharField(verbose_name='名称', max_length=32) class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名', max_length=32)
age = models.CharField(verbose_name='年龄', max_length=32)
level_choice = ((1, 'VIP'), (2, 'SVIP'), (3, 'PARTNER'))
level = models.SmallIntegerField(verbose_name='级别', choices=level_choice)
email = models.CharField(verbose_name='邮箱', max_length=32) # 创建外键
depart = models.ForeignKey(verbose_name="部门", to="Department", on_delete=models.CASCADE) # 多对多
roles = models.ManyToManyField(verbose_name="角色", to="Role")
# views.py
from rest_framework import serializers
from rest_framework.filters import BaseFilterBackend
from rest_framework.viewsets import ModelViewSet from api import models # Create your views here.
class UserSerializer(serializers.ModelSerializer):
level_text = serializers.CharField(source="get_level_display", read_only=True)
extra = serializers.SerializerMethodField(read_only=True) class Meta:
model = models.UserInfo
fields = ['username', 'age', 'email', "level_text", 'extra'] def get_extra(self, obj):
return '我是多余的' # 自定义Filter
class Filter1(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
age = request.GET.get('age') # 可以使用request.query_params
if not age:
return queryset
return queryset.filter(age=age) class Filter2(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
id = request.query_params.get('id')
if not id:
return queryset
return queryset.filter(id=id) class UserView(ModelViewSet):
filter_backends = [Filter1, Filter2] # 加入需要传递的Filter
queryset = models.UserInfo.objects.all() # GenericAPIView这个类提供的变量
serializer_class = UserSerializer

返回值:

源码流程

2. 第三方filter(常用)

在drf开发中有一个常用的第三方过滤器:DjangoFilterBackend。

pip install django-filter

注册app:

INSTALLED_APPS = [
...
'django_filters',
...
]

示例1: 简单

视图配置和应用:

# views.py
from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from app01 import models class UserModelSerializer(serializers.ModelSerializer):
level_text = serializers.CharField(
source="get_level_display",
read_only=True
)
extra = serializers.SerializerMethodField(read_only=True) class Meta:
model = models.UserInfo
fields = ["username", "age", "email", "level_text", "extra"] def get_extra(self, obj):
return 666 class UserView(ModelViewSet):
filter_backends = [DjangoFilterBackend, ]
filterset_fields = ["id", "age", "email"] queryset = models.UserInfo.objects.all()
serializer_class = UserModelSerializer def perform_create(self, serializer):
""" 序列化:对请求的数据校验成功后,执行保存。"""
serializer.save(depart_id=1, password="123")

示例2: 复杂

视图配置和应用(示例3):

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend, OrderingFilter
from django_filters import FilterSet, filters
from app01 import models class UserModelSerializer(serializers.ModelSerializer):
level_text = serializers.CharField(
source="get_level_display",
read_only=True
)
depart_title = serializers.CharField(
source="depart.title",
read_only=True
)
extra = serializers.SerializerMethodField(read_only=True) class Meta:
model = models.UserInfo
fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"] def get_extra(self, obj):
return 666 class MyFilterSet(FilterSet):
# /api/users/?min_id=2 -> id>=2
min_id = filters.NumberFilter(field_name='id', lookup_expr='gte') # /api/users/?name=wupeiqi -> not ( username=wupeiqi )
name = filters.CharFilter(field_name="username", lookup_expr="exact", exclude=True) # /api/users/?depart=xx -> depart__title like %xx%
depart = filters.CharFilter(field_name="depart__title", lookup_expr="contains") # /api/users/?token=true -> "token" IS NULL
# /api/users/?token=false -> "token" IS NOT NULL
token = filters.BooleanFilter(field_name="token", lookup_expr="isnull") # /api/users/?email=xx -> email like xx%
email = filters.CharFilter(field_name="email", lookup_expr="startswith") # /api/users/?level=2&level=1 -> "level" = 1 OR "level" = 2(必须的是存在的数据,否则报错-->内部有校验机制)
# level = filters.AllValuesMultipleFilter(field_name="level", lookup_expr="exact")
level = filters.MultipleChoiceFilter(field_name="level", lookup_expr="exact", choices=models.UserInfo.level_choices) # /api/users/?age=18,20 -> age in [18,20]
age = filters.BaseInFilter(field_name='age', lookup_expr="in") # /api/users/?range_id_max=10&range_id_min=1 -> id BETWEEN 1 AND 10
range_id = filters.NumericRangeFilter(field_name='id', lookup_expr='range') # /api/users/?ordering=id -> order by id asc
# /api/users/?ordering=-id -> order by id desc
# /api/users/?ordering=age -> order by age asc
# /api/users/?ordering=-age -> order by age desc
ordering = filters.OrderingFilter(fields=["id", "age"]) # /api/users/?size=1 -> limit 1(自定义搜索)
size = filters.CharFilter(method='filter_size', distinct=False, required=False) class Meta:
model = models.UserInfo
fields = ["id", "min_id", "name", "depart", "email", "level", "age", 'range_id', "size", "ordering"] def filter_size(self, queryset, name, value):
int_value = int(value)
return queryset[0:int_value] class UserView(ModelViewSet):
filter_backends = [DjangoFilterBackend, ]
filterset_class = MyFilterSet queryset = models.UserInfo.objects.all()
serializer_class = UserModelSerializer def perform_create(self, serializer):
""" 序列化:对请求的数据校验成功后,执行保存。"""
serializer.save(depart_id=1, password="123")

补充

lookup_expr有很多常见选择:

'exact': _(''),
'iexact': _(''), 'contains': _('contains'),
'icontains': _('contains'),
'startswith': _('starts with'),
'istartswith': _('starts with'),
'endswith': _('ends with'),
'iendswith': _('ends with'), 'gt': _('is greater than'),
'gte': _('is greater than or equal to'),
'lt': _('is less than'),
'lte': _('is less than or equal to'), 'in': _('is in'),
'range': _('is in range'),
'isnull': _(''), 'regex': _('matches regex'),
'iregex': _('matches regex'),

全局配置和应用:

# settings.py 全局配置

REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend',]
}

3. 内置filter

drf源码中内置了2个filter,分别是:

  • OrderingFilter,支持排序。

    from rest_framework import serializers
    from rest_framework.viewsets import ModelViewSet
    from app01 import models
    from rest_framework.filters import OrderingFilter class UserModelSerializer(serializers.ModelSerializer):
    level_text = serializers.CharField(
    source="get_level_display",
    read_only=True
    )
    depart_title = serializers.CharField(
    source="depart.title",
    read_only=True
    )
    extra = serializers.SerializerMethodField(read_only=True) class Meta:
    model = models.UserInfo
    fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"] def get_extra(self, obj):
    return 666 class UserView(ModelViewSet):
    filter_backends = [OrderingFilter, ]
    # ?order=id
    # ?order=-id
    # ?order=age
    ordering_fields = ["id", "age"] queryset = models.UserInfo.objects.all()
    serializer_class = UserModelSerializer def perform_create(self, serializer):
    """ 序列化:对请求的数据校验成功后,执行保存。"""
    serializer.save(depart_id=1, password="123")
  • SearchFilter,支持模糊搜索。

    from rest_framework import serializers
    from rest_framework.viewsets import ModelViewSet
    from app01 import models
    from rest_framework.filters import SearchFilter class UserModelSerializer(serializers.ModelSerializer):
    level_text = serializers.CharField(
    source="get_level_display",
    read_only=True
    )
    depart_title = serializers.CharField(
    source="depart.title",
    read_only=True
    )
    extra = serializers.SerializerMethodField(read_only=True) class Meta:
    model = models.UserInfo
    fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"] def get_extra(self, obj):
    return 666 class UserView(ModelViewSet):
    filter_backends = [SearchFilter, ]
    search_fields = ["id", "username", "age"] queryset = models.UserInfo.objects.all()
    serializer_class = UserModelSerializer def perform_create(self, serializer):
    """ 序列化:对请求的数据校验成功后,执行保存。"""
    serializer.save(depart_id=1, password="123")
    "app01_userinfo"."id" LIKE %18% ESCAPE '\'
    OR
    "app01_userinfo"."username" LIKE %18% ESCAPE '\'
    OR
    "app01_userinfo"."age" LIKE %18% ESCAPE '\'

DRF的filter组件的更多相关文章

  1. DRF的序列化组件

    目录 DRF的序列化组件 Serializer组件 序列化 反序列化 ModelSerializer组件 序列化和反序列化 自定义Response方法 基表相关 DRF中ORM的多表关联操作 外键设计 ...

  2. DRF(5) - 频率组件、url注册器、响应器、分页器

    一.频率组件 1.使用DRF简单频率控制实现对用户进行访问频率控制 1)导入模块,定义频率类并继承SimpleRateThrottle # 导入模块 from rest_framework.throt ...

  3. DRF框架(九)——drf偏移分页组件、drf游标分页组件(了解)、自定义过滤器、过滤器插件django-filter

    drf偏移分页组件 paginations.py from rest_framework.pagination import LimitOffsetPagination class MyLimitOf ...

  4. 第三章、drf框架 - 序列化组件 | Serializer

    目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...

  5. DRF的视图组件

    目录 DRF的视图组件 两大视图类 六大视图工具类 九大工具视图类 两大视图集基类 DRF的视图组件 DRF的视图组件大概分以下几类 两大视图类 APIView.GenericAPIView from ...

  6. drf偏移分页组件-游标分页-自定义过滤器-过滤器插件django-filter

    drf偏移分页组件 LimitOffsetPagination 源码分析:获取参数 pahenations.py from rest_framework.pagination import Limit ...

  7. DRF 解析器组件

    Django无法处理application/json协议请求的数据,即,如果用户通过application/json协议发送请求数据到达Django服务器,我们通过request.POST获取到的是一 ...

  8. Django框架(十八)—— drf:序列化组件(serializer)

    序列化组件 # 模型层 from django.db import models class Book(models.Model): nid = models.AutoField(primary_ke ...

  9. Django框架深入了解_03(DRF之认证组件、权限组件、频率组件、token)

    一.认证组件 使用方法: ①写一个认证类,新建文件:my_examine.py # 导入需要继承的基类BaseAuthentication from rest_framework.authentica ...

  10. drf框架 - 序列化组件 | ModelSerializer (查,增,删,改)

    ModelSerializer 序列化准备: 配置 settings.py # 注册rest_framework框架 INSTALLED_APPS = [ ... 'rest_framework' ] ...

随机推荐

  1. Q:windows系统如何开机启动批处理脚本

    方法1 1.win+r输入gpedit.msc进入本地策略管理器 2.点击windows设置下的脚本(启动/关机),然后双击启动. 3.点击添加,然后点击浏览,选择批处理文件然后点击确定. 方法2 也 ...

  2. fgets()函数的详解以及使用时需要注意的一些细节-C语言基础

    这篇文章要探讨的是"fgets()函数的详解以及使用时需要注意的一些细节".涉及fgets()函数的应用和需要注意的问题.属于C语言基础篇(持续更新). fgets()(函数原型: ...

  3. 更新Vue-cli4与Eslint插件自动保存

    Vue-cli更新 此更新为Vue-cli3更新为4,可使用node来查看本机的安装版本,vue -V,此版本(cli4)需要node v8.9 或更高版本 (推荐 v10 以上),查看node版本可 ...

  4. 记一次yapi部署过程

    一.为什么用yapi yapi基于文档注释生成,没有代码的入侵. 同一个工程的接口文档可以导出多个项目中,分权限查看. 可以本地化部署,统一的接口文档,支持其他的文档接入. 有idea插件支持,自动导 ...

  5. 手写 Java HashMap 核心源码

    手写 Java HashMap 核心源码 手写 Java HashMap 核心源码 上一章手写 LinkedList 核心源码,本章我们来手写 Java HashMap 的核心源码. 我们来先了解一下 ...

  6. nginx配置反向代理服务器,实现在https网站中请求http资源

    网站使用nginx作为服务器,协议从http升级为https的注意事项. 具体升级步骤请点击搜索 1.首先,修改宝塔面板配置 选择配置文件,http请求重定向为https.所有80端口请求都重定向为h ...

  7. 【读书笔记】排列研究-模式避免-基础Pattern Avoidance

    目录 模式避免的定义 避免Pattern q 的n-排列计数\(S_n(q)\) q长度是2 q长度是3 对一些模式q,做\(S_n(q)\)的阶估计 Backelin, West, and Xin给 ...

  8. 小笨自采集在线电脑壁纸 v2.0-支持移动端自适应,支持https

    这周闲着没事,翻着网站,记得去年的发表的一篇文章小笨分享一款高清电脑壁纸API,主要是将孟坤壁纸改造支持https,还加了一个搜索功能.以前的壁纸是这样的: 但是,不支持移动端浏览,于是小笨趁着这周周 ...

  9. 工良出品:包教会,Hadoop、Hive 搭建部署简易教程

    目录 导读 Hadoop.Hive 是什么 运行环境 Java 环境 Mysql 下载 Hadoop.Hive 和 驱动 安装 Hadoop core-site.xml hdfs-site.xml m ...

  10. 简述SpringAOP的实现原理

    ​ Spring默认采取的动态代理机制实现AOP,当动态代理不可用时 (代理类无接口)会使用CGlib机制. Spring提供了两种方式来生成代理对象:JDKProxy和Cglib,具体使用哪种方式生 ...