当前位置: 首页 > news >正文

DRF——Filter条件搜索模块

文章目录

      • 条件搜索
        • 自定义Filter
        • 第三方Filter
        • 内置Filter

条件搜索

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

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

在drf中也有相应组件可以支持条件搜索。

自定义Filter

自定义filter后,需要在view视图类中定义filter_backeds类变量,django会自动读取循环filter_backeds中的filter类并执行实例化对象的filter_query方法。(get,put,delete,patch都会执行,post不会)

在这里插入图片描述

# urls.pyfrom django.urls import path
from app01 import viewsurlpatterns = [path('api/users/', views.UserView.as_view({"get": "list", "post": "create"})),path('api/users/<int:pk>/', views.UserView.as_view({"get": "retrieve", "put": "update", "patch": "partial_update", "delete": "destroy"})),
]
# views.pyfrom rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import BaseFilterBackend
from app01 import modelsclass UserModelSerializer(serializers.ModelSerializer):level_text = serializers.CharField(source="get_level_display",read_only=True)extra = serializers.SerializerMethodField(read_only=True)class Meta:model = models.UserInfofields = ["username", "age", "email", "level_text", "extra"]def get_extra(self, obj):return 666class Filter1(BaseFilterBackend):def filter_queryset(self, request, queryset, view):age = request.query_params.get('age')if not age:return querysetreturn queryset.filter(age=age)class Filter2(BaseFilterBackend):def filter_queryset(self, request, queryset, view):user_id = request.query_params.get('id')if not user_id:return querysetreturn queryset.filter(id__gt=user_id)class UserView(ModelViewSet):filter_backends = [Filter1, Filter2]queryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef perform_create(self, serializer):""" 序列化:对请求的数据校验成功后,执行保存。"""serializer.save(depart_id=1, password="123")
第三方Filter

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

pip install django-filter

注册app:

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

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

最简单应用:

可以通过下载,django-filter组件,引入django_filter.rest_framework import DjangoFilterBancked。

在view视图类中定义filter_banckeds=[DjangoFilterBancked],和filterset_fields=[“id”,“name”,“age”]。

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

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

还可以通过定义类变量filterset_class来定义更复杂的查询变量条件,

flilter类应该继承FilterSet,(类的构建类似于MoldeForm)

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import FilterSet, filters
from app01 import modelsclass 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.UserInfofields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]def get_extra(self, obj):return 666class MyFilterSet(FilterSet):depart = filters.CharFilter(field_name="depart__title", lookup_expr="exact")min_id = filters.NumberFilter(field_name='id', lookup_expr='gte')class Meta:model = models.UserInfofields = ["min_id", "depart"]class UserView(ModelViewSet):filter_backends = [DjangoFilterBackend, ]filterset_class = MyFilterSetqueryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef perform_create(self, serializer):""" 序列化:对请求的数据校验成功后,执行保存。"""serializer.save(depart_id=1, password="123")

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

  • 构建filter类的字段:

    NumberFilter,CharFilter,BooleanFilter,MultipleChoiceFilter,BaseInFilter,NumericRangeFilter,OrderingFilter,

    还可以通过CharFilter使用自定义搜索的方法。

  • 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'),
    
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 modelsclass 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.UserInfofields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]def get_extra(self, obj):return 666class MyFilterSet(FilterSet):# /api/users/?min_id=2  -> id>=2min_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 NULLtoken = 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 10range_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 descordering = 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.UserInfofields = ["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 = MyFilterSetqueryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef 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',]
}
内置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 OrderingFilterclass 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.UserInfofields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]def get_extra(self, obj):return 666class UserView(ModelViewSet):filter_backends = [OrderingFilter, ]# ?order=id# ?order=-id# ?order=ageordering_fields = ["id", "age"]queryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef 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 SearchFilterclass 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.UserInfofields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]def get_extra(self, obj):return 666class UserView(ModelViewSet):# ?search=DP%Tfilter_backends = [SearchFilter, ]search_fields = ["id", "username", "age"]queryset = models.UserInfo.objects.all()serializer_class = UserModelSerializerdef perform_create(self, serializer):""" 序列化:对请求的数据校验成功后,执行保存。"""serializer.save(depart_id=1, password="123")
    "app01_userinfo"."id" LIKE %DPT% ESCAPE '\' 
    OR 
    "app01_userinfo"."username" LIKE %DPT% ESCAPE '\' 
    OR 
    "app01_userinfo"."age" LIKE %DPT% ESCAPE '\'
    

若有错误与不足请指出,关注DPT一起进步吧!!!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 8月跳槽进字节跳动测试岗了,面试真简单...
  • 【注解】反序列化时匹配多个 JSON 属性名 @JsonAlias 详解
  • 修改了原神4.8版本升级数据表
  • 关于前端form提交后端返回文件流触发浏览器下载(并发控制)
  • 程序员常用的10种算法
  • Pandas DataFrame 数据转换处理和多条件查询
  • 【模板】连接外围数据库
  • Java高效写入大量数据到Excel文件——使用Apache POI的SXSSFWorkbook
  • WIFI 频段及信道简介
  • 【摆脱被360安全卫士荼毒:使用这2个软件就够了】
  • GoFly快速开发后台框架当后端接口请求返回403提示码就跨域问题/请求端域名拦截问题
  • [数据集][目标检测]电力场景红外图像输电线路绝缘子检测数据集VOC+YOLO格式1846张1类别
  • 认识泛型VS包装类
  • 第5章 虚拟机的安装和使用
  • MyBatis-Plus 一、(基础应用)
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • Android系统模拟器绘制实现概述
  • canvas 绘制双线技巧
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • js写一个简单的选项卡
  • maya建模与骨骼动画快速实现人工鱼
  • miaov-React 最佳入门
  • Ruby 2.x 源代码分析:扩展 概述
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • Terraform入门 - 3. 变更基础设施
  • vue脚手架vue-cli
  • 从伪并行的 Python 多线程说起
  • 携程小程序初体验
  • 云大使推广中的常见热门问题
  • 终端用户监控:真实用户监控还是模拟监控?
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • #define 用法
  • $$$$GB2312-80区位编码表$$$$
  • $().each和$.each的区别
  • ${ }的特别功能
  • (2)Java 简介
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (ibm)Java 语言的 XPath API
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (不用互三)AI绘画工具应该如何选择
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (一)模式识别——基于SVM的道路分割实验(附资源)
  • (已解决)什么是vue导航守卫
  • (原)本想说脏话,奈何已放下
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • .NET CLR Hosting 简介
  • .net 生成二级域名
  • .NET 通过系统影子账户实现权限维持
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .net6 core Worker Service项目,使用Exchange Web Services (EWS) 分页获取电子邮件收件箱列表,邮件信息字段
  • .NET编程——利用C#调用海康机器人工业相机SDK实现回调取图与软触发取图【含免费源码】
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .net后端程序发布到nignx上,通过nginx访问
  • .Net中间语言BeforeFieldInit