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. 记安装MySQL数据库

    记录一次自己动手安装MySQL数据库所踩的坑   MySQL安装包与操作系统匹配 安装包有amd和Intel,32位.64位多种组合需要确认仔细使用者操作系统和CPU型号 例如我使用的是CentOS ...

  2. [C#]Windows窗体应用基础-1

    代码参考: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sy ...

  3. c语言数据结构 树的基本操作

    树的基本操作有创建,插入,删除,以及各种遍历的应用,如:利用后序遍历求高度,利用前序遍历求层数的结点 基本算法思路:创建二叉树函数参数必须接受二级指针!如果使用同级指针,无法返回创建后的结果,利用递归 ...

  4. 初识MPC

    MPC调研报告 ​ 这是一篇关于MPC的调研报告,主要介绍了我对MPC领域的一些基础认识.全文按照这样的方式组织:第一节我介绍了什么是MPC以及MPC的起源:第二节介绍了MPC领域常用的一些符号和安全 ...

  5. Laravel安装第一步:Windows 10 上laravel下载与安装需要注意。

    1.下载了laravel,查看composer.json文件,搞清楚它需要的PHP版本 2.不要用 composer install !!! 用  composer -vvv install   这样 ...

  6. 京东薅羊毛脚本-Docker

    一.安装好docker,然后创建容器: 注1:如果是旁路由,建议用--network host \代替-p 5678:5678 \这一行. 注2:如果想要看到lxk0301大佬的js脚本,并且重新部署 ...

  7. Python项目案例开发从入门到实战-1.5Python文件的使用

    Python对文件的操作通常按照三个步骤进行: un 使用open()函数打开(或建立)文件,并返回一个file对象. deux 使用file对象的读写方法对文件进行读写操作. trois 使用fil ...

  8. 给jui(dwz)的navTab换一套漂亮的图标

    上次讲了给jui(dwz)的菜单树换一套漂亮的图标,这次讲一下在点击菜单后,怎么把设置的漂亮图标带到navTab上去. 官方的navTab是这样显示的,除了默认的我的主页外,tab页上只有标题没有图标 ...

  9. 2-2 理解const

    1 const 在引用中注意不能为常量绑定一个非常量的引用 在指针中区分low-level const和top-level const const通常用于定义常量,一经定义不许修改,且使用const必 ...

  10. superset连接mysql数据

    目前superset的官网没给出windows的安装教程,但是实际操作是可以的,网上有很多教程,再次就不赘述! 本篇随笔是介绍superset如何连接mysql数据源,本人踩坑踩了一整天.=_= ~~ ...