有时候前端需要各种各样的过滤查询,如果自己写多少有点麻烦和冗余。使用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. 谈一谈电商API接口

    随着电商行业的快速发展,越来越多的企业开始意识到并利用API接口来提升其电商平台的功能和效率.但是,对于普通用户来说,对API接口可能还不太了解.那么,什么是API接口,特别是电商API接口呢?本文将 ...

  2. CodeForces-1278B-A-and-B

    题意 对于\(t(1\leq t\leq 100)\)个测试点,给两个数\(a\)和\(b\),作如下操作: 第一次挑一个数使其加\(1\),第二次挑一个数使其加\(2\),以此类推,最后两个数相等, ...

  3. 【题解】Educational Codeforces Round 141(CF1783)

    评价:educational A.Make it Beautiful 题目描述: 如果一个数组中存在一个数恰好等于该数前面所有数之和,那么这个数组就是丑的.如果一个数组不是丑的,就是美的. 比如说: ...

  4. golang .(type)语法

    一直弄不懂 .(type) 是啥,在 liteide 中输出 (1+1).(type),提示: use of .(type) outside type switch 于是搜索到这个文章: 作者:翔云翔 ...

  5. MongoDB慢日志

    MongoDB慢日志 ​ 熟悉 Mysql 的人应该知道,Mysql 是有个慢查询日志的,它可以帮助我们进行优化我们的 sql,并提高我们系统的稳定性和流畅性.那么 MongoDB 中是否也有类似的功 ...

  6. ModelScope

    欢迎来到ModelScope平台!本篇文章介绍如何快速开始使用ModelScope平台上的模型,包括所需的基础概念,环境安装,模型推理和训练的快速实践示例. 如何开始# 如果你是新手,想快速体验产品, ...

  7. MySQL误删恢复方法1

    MySQL不同于oracle,没有闪回查询这类概念,但网上流传几个闪回的开源工具如 binglog2sql.MyFlash,可以使用binglog日志进行误操作数据的恢复. 笔者以前测试过 bingl ...

  8. XX-net安装

    1.下载https://github.com/XX-net/XX-Net 2. 3. 4.运行google浏览器 5.找到安装XX-net的位置,点击即可访问google ps:校园网用户可以直接使用 ...

  9. 8.12 dp模拟赛总结

    考场概况: 开考发现题目竟然不保证按难度顺序排序QAQ 正序开题, \(T1\) 显然是数位 \(dp\) 然而没学过不会写,顺手打了 \(30pts\) 暴力走人. \(T2\) 期望 \(dp\) ...

  10. JS动态在父元素里追加元素——insertAdjacentHTML

    insertAdjacentHTML() 方法将指定的文本解析为 Element 元素,并将结果节点插入到 DOM 树中的指定位置.它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素.这避 ...