DRF的filter组件

这篇具有很好参考价值的文章主要介绍了DRF的filter组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

返回值:

DRF的filter组件

源码流程

DRF的filter组件

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,支持模糊搜索。文章来源地址https://www.toymoban.com/news/detail-422380.html

    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组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity3D】Unity 组件 ① ( 组件 Component 概念 | Transform 组件和 Light 组件 | Mesh Filter 组件和 Mesh Renderer 组件 )

    组件 Component 是 选中 游戏物体 GameObject 后 , 在 Inspector 检查器 窗口 中 , 查看到的内容 ; 组件 Component 代表了 游戏物体 GameObject 的一种功能 ; 空物体 只有 Transform 组件 , 只能提供 坐标 , 旋转角度 , 缩放倍数 功能 ; 平行光源 物体 有 Light 组件 提供光照功能 ; 立方体 物体 有 M

    2024年02月06日
    浏览(35)
  • PHP伪协议filter详解,php://filter协议过滤器

    「作者主页」: 士别三日wyx 「作者简介」: CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」: 对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 php:// 用来访问输入和输出流(I/O streams)。 输入/输出流也就是 「数据流」

    2024年02月08日
    浏览(29)
  • SpringCloudAlibaba Gateway(二)详解-内置Predicate、Filter及自定义Predicate、Filter

    ​ Predicate(断言),用于进行判断,如果返回为真,才会路由到具体服务。SpirnngCloudGateway由路由断言工厂实现,直接配置即生效,当然也支持自定义路由断言工厂。 ​ SpringCloudGateway路由断言工厂实现有很多,可以帮助开发者完成不同的功能。 AfterRoutePredicateFactory :设定日期参

    2024年02月10日
    浏览(35)
  • Spring Boot 3.1.2版本使用javax.servlet.Filter时,发现Filter不起作用

    在学习Filter的过程中,我实现了Filter的init和destory方法以及doFilter方法后,运行SpringBoot程序发现,我的控制台中并没有输出ini和destory中的调试信息。 代码如下:  可以看到控制台中并没有输出initialize Filter和destory Filter等信息  利用postman发送http请求发现access Filter也没有输出

    2024年03月09日
    浏览(30)
  • Filter&ajax

    概念:表示过滤器,是JavaWeb三大组件(Servlet,Filter,Listener)之一; 过滤器可以把对资源的请求 拦截 下来,从而实现一些特殊的功能. 过滤器可以完成一些 通用 操作比如:登录添加购物车,视频广告,敏感字符处理等等... 用户检测,搜索提示等 异步 的JavaScript ① 与服务器进行数据交换:

    2024年02月19日
    浏览(23)
  • 认识Filter(过滤器)

    Filter介绍 在计算机编程中,Filter(过滤器)是一种用于对数据流进行处理的软件组件。Filter 的作用是从输入流中获取数据,对其进行处理后再将其写入输出流中。Filter 组件通常用于数据校验、数据转换、数据压缩等方面,以及对网络通信进行处理。在 Web 开发中,Filter 是

    2024年02月02日
    浏览(39)
  • Filter 过滤器

    Filter过滤器介绍 这里我们讲解Filter的执行流程,从下图可以大致了解到,当客户端发送请求的时候,会经过过滤器,然后才能到我们的servlet,当我们的servlet处理完请求之后,我们的response还是先经过过滤器才能到达我们的客户端,这里我们进行一个代码的演示,看看具体执

    2024年02月02日
    浏览(33)
  • filter函数的用法

    filter函数是数组里的一个方法,它主要起到的是过滤作用,filter()创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 (1)filter() 不会对空数组进行检测; (2)filter() 不会改变原始数组。 !!!需要注意的一点,filter函数存在一个隐式转换机制

    2024年02月16日
    浏览(34)
  • 什么是Filter?

    Filter(过滤器)是Java Web中的一种重要组件,可以对请求和响应进行拦截处理,对数据进行过滤和处理。Filter可以实现许多功能,如:鉴权、日志记录、字符编码转换、数据压缩、请求重定向等等。 在Java Web应用程序中,使用Filter非常简单,只需编写一个类实现javax.servlet.Fi

    2024年02月01日
    浏览(11)
  • 登录校验-Filter-详解

    目录 执行流程 拦截路径 过滤器链  小结 过滤器Filter拦截到请求之后,首先执行方放行之前的逻辑,然后执行放行操作( doFilter ),然后会访问对应的Web资源(对应的Controller类),Controller类处理完请求后,然后执行放行之后的逻辑,最后将响应结果返回给前端。 Filter可以

    2024年02月11日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包