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. 基于Dijkstra算法的郑州地铁路径规划

    需要引入geopy库 pip install geopy 安装即可 import requests from bs4 import BeautifulSoup import pandas as pd ...

  2. linux shell 目录

    linux shell 目录 目录 linux shell 目录 类型 unix支持三大主流shell linux支持的shell(可有四种) 部分相关命令 查询进程 ps pstree kill 查 ...

  3. mysql 递归

    MySQL中实现递归查询   对于数据库中的树形结构数据,如部门表,有时候,我们需要知道某部门的所有下属部分或者某部分的所有上级部门,这时候就需要用到mysql的递归查询 1.创建表 DROP TAB ...

  4. 解决和根源:Unsolicited response received on idle HTTP channel starting with xxx

    环境:golang,使用http client,服务器:iis +aspx.net动作:head请求或其他此问题见于各种请求情况.核心是,http在活动期间收到了非预期的信息.一开始我也很纳-闷,因为 ...

  5. WPF dxe:ComboBoxEdit 选择项后并可编辑值

    有个需要,在ComboBoxEdit中选择多个值,并且要求可以直接在后面添加新的值. 开始的时候绑定列表,设置DisplayMember,不能修改. 然后绑定List<string>,不设 ...

  6. centos下vi 命令用法

    vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...

  7. gstreamer样例

    #!/bin/bash xrandr -s 0 --output DSI-1 xrandr -s 0 --output HDMI-1 xrandr --fb 1024x600 --output DSI ...

  8. AWS、谷歌云、Azure:云计算安全功能比较

    每个云平台提供给客户用以保护其云资产安全工具和安全功能都不一样. 公有云安全建立在共担责任概念基础之上:大型云服务提供商交付安全超大规模环境,但保护推上云端一切是客户自己责任.对企业而言,这种安全责任 ...

  9. DataTable 导出到TXT

    public static string cExportTXT(DataView dv) { try { SaveFileDialog saveFileDialog1 = new SaveFileDi ...

  10. adb shell monkey

    monkey 在模拟器或真机里在,.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),打开app 查看包名 adb shell dumpsys window windows | f ...