有时候前端需要各种各样的过滤查询,如果自己写多少有点麻烦和冗余。使用django-filter就可以很好的解决这个问题。

django-filter可以用在django上, 也与配合drf一起使用。

主要区别在于drf要集成的FilterSet和django的不是同一个,别的都差不多。

下面展示配合drf使用。来实现搜索过滤的功能。

安装

pip install django-filter

配置

'django_filters' 添加到Django的 INSTALLED_APPS 中:

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

DRF添加默认过滤后端:

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

或者将过滤器后端类添加到单个视图或视图集。

rom django_filters.rest_framework import DjangoFilterBackend

class UserListView(generics.ListAPIView):
...
filter_backends = [DjangoFilterBackend]

入门使用

如果你只是需要对模型类的字段进行等值过滤,则可以参考下面的例子,这样能够快速实现等值过滤。

class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend] # 使用filterset_fields属性,指定需要等值过滤的模型类字段名
filterset_fields = ['category', 'in_stock']

这将自动为给定字段创建一个 FilterSet 类,并允许您发出如下请求:

http://example.com/api/products?category=clothing&in_stock=True

如果需要实现其他条件、模糊查询等,则需要自定义FilterSet.

自定义FilterSet实现更高级的过滤规则

https://django-filter.readthedocs.io/en/stable/guide/usage.html

FilterSet类的定义的写法和DRF的序列化器几乎差不多了,因为他们都是参照django的ModelForm。

实例:

# 这里导的是django_filters.rest_framework下的filter.FilterSet,不要导错了
# from django_filters import FilterSet 这个是给django用的。
from django_filters import rest_framework as filters # 自定义FilterSet
class BookInfoFilter(filters.FilterSet): **# 这种叫直接声明过滤器字段,灵活性高,但如果字段比较多会相相对冗余一些..**
# **格式:**
# url中查询字符串key名 = 过滤器类型(field_name=模型类字段名, lookup_expr=过滤表达式关键词)
# lookup_expr: django的查询过滤表达式关键词,比如exact、startswith、in、gt等等...
name_like = filters.CharFilter(field_name="name", lookup_expr="icontains")
# 然后后台进行orm查询自动生成的表达式为:name__icontains执行过滤(这个就是django的过滤表达式而已) class Meta:
model = BookInfo # 需要指定django模型类 # 如果fields 给定的是一个元组、列表,则默认自动生成的字段类只是等值过滤(没有其他过滤规则)
# 那还不如直接在视图中指定filterset_fields属性,这样更快捷。
# 所以一般我们只有实现高级过滤才会自定义FilterSet,并定义过滤器字段的查找表达式
fields = ['name', ] # exclude 从自动过滤器生成中排除的字段。但不会禁用直接在 FilterSet 上声明的过滤器。
# exclude不能同fields同时使用。
# exclude=["is_delete"] **# 进行name字段模糊查询时就可以使用以下url:**
# http://127.0.0.1:8000/book/viewset/?name_like=八

视图代码:

class BookInfoModelViewSet(ModelViewSet):
filter_backends = [django_filters.rest_framework.DjangoFilterBackend] # filterset_fields = ['readcount', 'commentcount'] # filter_class不能和filterset_fields同时指定!
# 因为filterset_fields本身就自动帮你生成一个FilterSet,实现最简单的字段等值过滤查询!
filter_class = BookInfoFilter

使用Meta.fileds来定义过滤器

原来直接定义过滤器字段,如果需要过滤的字段多则带啊吗相对冗长,如下:

class BookInfoFilter(filters.FilterSet):
name_like = filters.CharFilter(field_name="name", lookup_expr="icontains")
pub_data_year = filters.CharFilter(field_name="pub_date", lookup_expr="year__exact")
pub_data_year_gt = filters.CharFilter(field_name="pub_date", lookup_expr="year__gt")
.... class Meta:
model = BookInfo # 需要指定django模型类
fields = ['name', 'pub_date']

通过Meta.fields属性来定义过滤器

class BookInfoFilter(filters.FilterSet):
#name_like = filters.CharFilter(field_name="name", lookup_expr="icontains")
#pub_data_year = filters.CharFilter(field_name="pub_date", lookup_expr="year__exact")
#pub_data_year_gt = filters.CharFilter(field_name="pub_date", lookup_expr="year__gt") class Meta:
model = BookInfo
# fields = ["name",]
fields = {
# 使用fileds来定义的话,URL的查询字符串会变成这样:
# ?name=xxx # 精确匹配,等值匹配extra不需要加上就可以查询。
# ?name__icontains=xxx # 模糊匹配
"name": ["exact", "icontains",], # ?pub_data__year__gt=xxx
# ?pub_data__year__lt=xxxx
# ?pub_data__year=xxx
# ?pub_data=xxx # 日期年月日用”-“或者”/“分割,比如:2022-02-02、2023/02/02
"pub_date": ["year__gt", "year__lt", "year__exact", "exact"],
}

两种方法总结:

  1. 如果直接手动声明过滤器字段,则灵活较大,但是如果你需要过滤很多规则时,代码就会很多,相对冗余。好处是可以改变get查询字符串中key的名字。
  2. 使用fields属性通过字典的形式定义,代码比较简洁,但是无法改变get查询字符串中key的名字。

使用Filter.method来自定义过滤规则

觉得django的过滤表达式不够用?

您可以通过指定 method 来执行过滤来控制过滤器的行为。请注意,您可以访问过滤器集的属性,例如 request

class F(django_filters.FilterSet):
username = CharFilter(method='my_custom_filter') class Meta:
model = User
fields = ['username'] def my_custom_filter(self, queryset, name, value):
return queryset.filter(**{
name: value,
})

更详细的用法见:https://django-filter.readthedocs.io/en/stable/ref/filters.html#filter-method

更改主查询结果集

默认情况下,FilterSet是直接模型类.objects.all()来获取所有结果集,然后再根据你指定的Filter过滤器来过滤的。

如果想改变主查询结果集,可以重写FilterSet.qs()方法.

例如,您可以将博客文章过滤为仅包含已发布的文章和登录用户拥有的文章(可能是作者的草稿文章)。

class ArticleFilter(django_filters.FilterSet):

    class Meta:
model = Article
fields = [...] @property
def qs(self):
parent = super().qs
author = getattr(self.request, 'user', None) return parent.filter(is_published=True) \
| parent.filter(author=author)

django-filter的详细使用的更多相关文章

  1. Windows 10 搭建 Django 环境(详细教程)

    Windows 10 搭建 Django 环境(详细教程) https://blog.csdn.net/HappyLittleMouse/article/details/81360272#1.%20P ...

  2. Django模版中的过滤器详细解析 Django filter大全

    就象本章前面提到的一样,模板过滤器是在变量被显示前修改它的值的一个简单方法. 过滤器看起来是这样的: {{ name|lower }} 显示的内容是变量 {{ name }} 被过滤器 lower 处 ...

  3. Django filter中用contains 在mysql中的问题

    用PYTHON ,DJANGO 做站,在通常的情况下,需要用到 orM 的查询方法,比如object.filter(tag__contains='keywords').... 在这种情况下,如果你跟踪 ...

  4. django filter or 多条件查询

    功能:django中实现多条件查询 或关系: from django.db.models import Q return qs.filter(Q(notice_to_group__contains=' ...

  5. 【Python】Django filter 如何支持 or 条件过滤?

    from django.db.models import Q Item.objects.filter(Q(creator=owner) | Q(moderated=False)) 代码示例: if(r ...

  6. Django日志记录详细的报错信息

    当服务器500错误的时候,普通日志只会记录一行500的request信息,并不会记录详细的报错定位 [ERROR] 2019-06-12 15:07:03,597 "GET /api/v1/ ...

  7. filter的详细配置

    我们已经了解了filter的基本用法,还有一些细节配置在特殊情况下起作用. 在servlet-2.3中,Filter会过滤一切请求,包括服务器内部使用forward转发请求和<%@ includ ...

  8. Django视图层详细介绍

    1 视图函数 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. ...

  9. PyCharm 创建指定版本的 Django (超详细图解)

    最近在学习胡阳老师(the5fire)的<Django企业级开发实战>,想要使用pycharm创建django项目时,在使用virtualenv创建虚拟环境后,在pycharm内,无论如何 ...

  10. Python3之Django框架搭建详细步骤

    安装Django 自行下载的pip,可执行如下命令: pip install django 下载python3版本可以自带pip3 ,命令如下: pip3 install django 此命令会下载d ...

随机推荐

  1. 图解Spark Graphx基于connectedComponents函数实现连通图底层原理

    原创/朱季谦 第一次写这么长的graphx源码解读,还是比较晦涩,有较多不足之处,争取改进. 一.连通图说明 连通图是指图中的任意两个顶点之间都存在路径相连而组成的一个子图. 用一个图来说明,例如,下 ...

  2. git pull 强制覆盖本地代码

    使用git pull更新本地代码,报以下错误: 解决办法如下. 1.备份本地代码 备份,可以考虑直接复制一份项目保存 2.远程覆盖本地 远程覆盖本地容易出现远程和本地冲突的情况 解决办法如下: //1 ...

  3. 触动精灵生成的APK文件如何加固保护

    触动精灵是一款模拟手机触摸.按键操作的软件,通过制作脚本,可以让触动精灵代替双手,自动执行一系列触摸.按键操作, 深受一些极客开发者喜爱. 触动精灵生成的APK文件自带了一些基础的加密,可以保护APK ...

  4. 钉钉旧版服务端SDK支持异步方法的升级改造

    最近项目中需要对接钉钉,有些钉钉 API 的访问需要使用旧版服务端 SDK 才能搞定,但是这个 SDK 使用的还是 .NET Framework 2.0 框架,不能跨平台部署,也不支持 async\a ...

  5. 在线问诊 Python、FastAPI、Neo4j — 创建 检查节点

    目录 症状数据 创建节点 根据不同的症状,会建议做些相对应的检验.检查 症状数据 examine_data.csv 建议值用""引起来.避免中间有,号造成误识别 检查 " ...

  6. 每日一题:如何判断是否是数组,一个既简单又复杂的问题。(不要再用Object.prototype.toString.call、instance of判断了!!!)

    1.不要使用Object.prototype.toString.call() 正常情况下: const arr = [1,2,3,4,5] const obj = {} console.log(Obj ...

  7. Teamcenter RAC 开发之《Excel模版导出》

    背景 在做 Teamcenter RAC客制化表单后,TMD肯定有一个需求要导出表单,毕竟所谓的客制化表单就是从纸质表单中出来的,那么写代码必不可少......... 那么问题来了,对于一个Excel ...

  8. heygen模型接口 简单使用 java版

    HeyGen - AI Spokesperson Video Creator  官网地址 Create a video (heygen.com) api地址 简介: 公司最近对ai方面业务比较感兴趣了 ...

  9. Vue2系列(lqz)——Vue基础

    文章目录 Vue介绍 一 模板语法 1.1 插值 1.1.1 概述 1.1.2 案例 二 指令 2.1 文本相关指令 2.2 事件指令 2.3 属性指令 三 class与style 3.1 class ...

  10. 前端三件套系例之HTML——HTML5基础

    1.HTML 1-1 什么是HTML HTML是用来制作网页的标记语言 HTML是Hypertext Markup Language的英文缩写,即超文本标记语言 HTML语言是一种标记语言,不需要编译 ...