Django一分钟:lookupAPI详解,使用django orm生成高效的WHERE子句
一、Lookup API概述
Lookup API是Django用于构建数据库查询WHERE
子句的API。
Lookup API的核心包含两部分:
RegisterLookupMixin
:为子类提供注册lookup的方法Query Expression API
:一个接口,规定了可以被注册为lookup的类需要实现的方法。
在Django中有两个实现了Query Expression API
的基类分别是:Lookup
和Transform
;前者用于声明查询条件,后者专注于对字段做转换。两者都实现了Query Expression API
,都可以被注册为lookup,可以单独使用,也可以互相配合。
lookup是一个比较抽象的名词,它描述的是搜索和过滤条件,而不是查找这个动作本身。对字段注册lookup,我们就能构造查询表达语句,Django会将其编译为合适的SQLWHERE
子句。
二、Lookup基类
前面提到实现Query Expression API
的基类分别是Lookup
和Transform
。首先介绍Lookup
类,它是我们构造查询语句的主力,我们从自定义一个Lookup
的子类出发来了解它的工作原理。
1. 自定义Lookup
尝试实现这样一件事情,将User.objects.filter(username__is='Mario')
转化为SQL:
"user"."username" IS 'mario'
当然SQL语句中不存在"IS",这样只是方便理解。实现这个功能需要两个步骤:
- 声明一个
Lookup
的子类,并重写as_sql()
方法:
from django.db.models import Lookupclass Is(Lookup):lookup_name = "is"def as_sql(self, compiler, connection):lhs, lhs_params = self.process_lhs(compiler, connection)rhs, rhs_params = self.process_rhs(compiler, connection)params = lhs_params + rhs_paramsreturn "%s IS %s" % (lhs, rhs), params
- 注册新声明的lookup类
Is
:
需要lookup在某个字段上生效,就需要调用这个字段上的register_lookup
方法进行注册。Filed
继承了RegisterLookupMixin
类,因此可以使用其提供的register_lookup
方法注册lookup。为Field
注册lookup,其所有子类就都可以使用此lookup:
from django.db.models import FieldField.register_lookup(Is)
Filed
提供了装饰器方法注册lookup:
from django.db.models import Field@Field.register_lookup
class Is(Lookup): ...
使用新定义的Is
查找类的方法有两种:
- 构造
<lhs>__<lookup_name>=<rhs>
形式的查询表达语句:
from django.contrib.auth.models import User
q = User.objects.filter(username__is="mairo")
q.query
print(q.query)
编译的SQL语句:
SELECT ...略 FROM "auth_user" WHERE "auth_user"."username" IS mairo
- 使用创建实例的形式
q = User.objects.filter(username__is="mairo")from django.db.models import F
q2 = User.objects.filter(Is(F('username'), 'mario'))
编译的SQL语句与上面的方法完全一致,两种方法是等效的。
2. Django内置的lookup
Django内置了很多lookup,在django.db.models.lookups
目录下你可以找到它们:
...
@Field.register_lookup
class GreaterThan(FieldGetDbPrepValueMixin, BuiltinLookup):lookup_name = "gt"@Field.register_lookup
class GreaterThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup):lookup_name = "gte"
...
介绍两种常用的内置lookup:
- exact
默认情况下当你没有提供查找类型的时候默认使用exact
:
Entry.objects.get(id=14)
Entry.objects.get(id__exact=14)
# 上面两个完全一致,准确来说django将id=14默认视为id__exact=14
等效SQL语句:
SELECT ... WHERE id = 14;
- in
Entry.objects.filter(id__in=[1, 3, 4])
等效SQL语句:
SELECT ... WHERE id IN (1, 3, 4);
三、Transform基类
与Lookup
类相同Transform
类及其子类也可以被注册为lookup,但Transform
与Lookup
不同,Transform 更加关注的是如何改变字段值,而不是直接进行值的比较。通过使用 Transform
,你可以对数据库中的数据执行诸如转换为小写、截取字符串的一部分、日期时间的格式化等操作。通常会和Lookup
配合使用,它主要做预处理工作。它是数据库级别的转换,具有很好的性能。
1. 自定义Transform
from django.db.models import Transform
from django.db.models import IntegerFieldclass AbsoluteValue(Transform):lookup_name = "abs"function = "ABS"IntegerField.register_lookup(AbsoluteValue)
Transform
在源码中继承了两个类class Transform(RegisterLookupMixin, Func)
,可以说它是一个特殊的Func
,在声明时就规定好了用于转换的function
,因此只接收一个参数。
- 使用示例1:
Experiment.objects.filter(change__abs=27)
生成的SQL:
SELECT ... WHERE ABS("experiments"."change") = 27
注意这里django实际上将change__abs=27
视作 change__abs__exact=27
。
- 使用示例2:
Experiment.objects.filter(change__abs__lt=27)
生成的SQL:
SELECT ... WHERE ABS("experiments"."change") < 27
2. 内置的Transform
- year
Blog.objects.filter(time__year__gt=2023)
生成的SQL
SELECT ... FROM "snippets_blog" WHERE "snippets_blog"."time" > 2023-12-31 23:59:59.999999+00:00
Django内置了很多中方便的transform,这里不做赘述。
四、lookup表达语句的构成
一个lookup表达语句可以由三部分构成,组合使用可以构造强大高效的查询语句。
- field:如
Book.objects.filter(author__best_friends__first_name...)
- Transform:如
__lower__first3chars__reversed
- lookup:如
__icontains
默认__exact
五、总结
- lookup API是Django中一个很重要的功能,它的主要工作就是构造查询的
WHERE
子句。 - Django已经内置了很多使用的lookups帮助我们快速构造查询语句。
- Django允许我们自定义lookups实现复杂的查询需求。
相关文章:

Django一分钟:lookupAPI详解,使用django orm生成高效的WHERE子句
一、Lookup API概述 Lookup API是Django用于构建数据库查询WHERE子句的API。 Lookup API的核心包含两部分: RegisterLookupMixin:为子类提供注册lookup的方法Query Expression API:一个接口,规定了可以被注册为lookup的类需要实…...

信息安全工程师(8)网络新安全目标与功能
前言 网络新安全目标与功能在当前的互联网环境中显得尤为重要,它们不仅反映了网络安全领域的最新发展趋势,也体现了对网络信息系统保护的不断加强。 一、网络新安全目标 全面防护与动态应对: 目标:建立多层次、全方位的网络安全防…...

返利机器人在电商返利系统中的负载均衡实现
返利机器人在电商返利系统中的负载均衡实现 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们来聊一聊如何在电商返利系统中实现返利机器人的负载均衡,尤其是在面对高并发和大量…...

MATLAB中typecast函数用法
目录 语法 说明 示例 将整数转换为相同存储大小的无符号整数 将 8 位整数转换为单精度 将 32 位整数转换为 8 位整数 将 8 位整数转换为 16 位整数 提示 typecast函数的功能是在不更改基础数据的情况下转换数据类型。 语法 Y typecast(X,type) 说明 Y typecast(X,…...

植物大战僵尸【源代码分享+核心思路讲解】
植物大战僵尸已经正式完结,今天和大家分享一下,话不多说,直接上链接!!!(如果大家在运行这个游戏遇到了问题或者bug,那么请私我谢谢) 大家写的时候可以参考一下我的代码思…...

变压器设备漏油数据集 voc txt
变压器设备漏油数据集 油浸式变压器通常采用油浸自冷式、油浸风冷式和强迫油循环三种冷却方式。该数据集采集于油浸式变压器的设备漏油情况,一般用于变电站的无人巡检,代替传统的人工巡检,与绝缘子的破损检测来源于同一课题。数据集一部分来自…...

算法练习题25——leetcode3279统计重新排列后包含另一个字符串的子字符串的数目(滑动窗口 双指针 哈希)
题目描述 解题思路 本题用到了滑动窗口 双指针 哈希 刚开始我是没读懂题的因为我笨 我想把我的思路说一下 左端不轻易缩小 只有找到跟word2匹配了 比如说abbcdd 遍历到c的时候才能匹配这个word2 对吧 那么之后加上以一个d或者俩d 都符合了 然后我们算完了 才能缩小左端 扩大…...

JavaEE: 深入探索TCP网络编程的奇妙世界(二)
文章目录 TCP核心机制TCP核心机制二: 超时重传为啥会丢包?TCP如何对抗丢包?超时重传的时间设定超时时间该如何确定? TCP核心机制 前一篇文章 JavaEE: 深入探索TCP网络编程的奇妙世界(一) 书接上文~ TCP核心机制二: 超时重传 在网络传输中,并不会一帆风顺,而是可能出现&qu…...

GPT1-GPT3论文理解
GPT1-GPT3论文理解 视频参考:https://www.bilibili.com/video/BV1AF411b7xQ/?spm_id_from333.788&vd_sourcecdb0bc0dda1dccea0b8dc91485ef3e74 1 历史 2017.6 Transformer 2018.6 GPT 2018.10 BERT 2019.2 GPT-2 2020…...

C/C++内存管理 ——
目录 五、C/C内存管理 1、C/C内存分布 2、C语言中动态内存管理方式:malloc/calloc/realloc/free 3、C内存管理方式 1.new/delete操作内置类型 2.new和delete操作自定义类型 4、operator new与operator delete函数 5、new和delete的实现原理 1.内置类…...

深度学习02-pytorch-04-张量的运算函数
在 PyTorch 中,张量(tensor)运算是核心操作之一,PyTorch 提供了丰富的函数来进行张量运算,包括数学运算、线性代数、索引操作等。以下是常见的张量运算函数及其用途: 1. 基本数学运算 加法运算:…...

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【文件系统】上
往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核(LiteOS-M) 轻量系统内核&#…...

NISP 一级 | 8.4 《网络安全法》
关注这个证书的其他相关笔记:NISP 一级 —— 考证笔记合集-CSDN博客 2017 年 6 月 1 日,《中华人民共和国网终安全法》(以下简称《网终安全法》)正式实施。这是我国第一部全面规范网络空间安全管理方面问题的基础性法律࿰…...

实现人体模型可点击
简化需求:实现项目内嵌人体模型,实现点击不同部位弹出部位名称 一:优先3d, 方案:基于three.js,.gltf格式模型,vue3 缺点:合适且免费的3d模型找不到,因为项目对部位有要…...

C++ | Leetcode C++题解之第429题N叉树的层序遍历
题目: 题解: class Solution { public:vector<vector<int>> levelOrder(Node* root) {if (!root) {return {};}vector<vector<int>> ans;queue<Node*> q;q.push(root);while (!q.empty()) {int cnt q.size();vector<…...

Pandas简介
Pandas 是一个流行的开源数据分析库,它是基于 NumPy 构建的,为 Python 编程语言提供了高性能、易用的数据结构和数据分析工具。Pandas 主要用于数据清洗、数据转换、数据分析等任务,使得数据处理工作变得更加高效和便捷。 Pandas 的两个主要…...

Python | Leetcode Python题解之第430题扁平化多级双向链表
题目: 题解: class Solution:def flatten(self, head: "Node") -> "Node":def dfs(node: "Node") -> "Node":cur node# 记录链表的最后一个节点last Nonewhile cur:nxt cur.next# 如果有子节点&#…...

机器人机构、制造
简单整理一下,在学习了一些运动学和动力学之类的东西,简单的整合了一些常用的机械结构和图片。 1.电机: 市面上的电机有:直流电机,交流电机,舵机,步进电机,电缸,无刷电…...

《拿下奇怪的前端报错》:nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践
有些前端的小伙伴可能会好奇,nvm是什么?这里接简单介绍下,它是一个Nodejs版本管理工具。为什么需要它呢?当然是需要多个Nodejs版本的时候,那什么时候需要多个Nodejs版本?那肯定是在有点年头的公司了&#x…...

5.《DevOps》系列K8S部署CICD流水线之K8S通过Yaml部署GitLab
架构 服务器IP服务名称硬件配置192.168.1.100k8s-master8核、16G、120G192.168.1.101k8s-node18核、16G、120G192.168.1.102k8s-node28核、16G、120G192.168.1.103nfs2核、4G、500G操作系统:Rocky9.3 后续通过K8S部署Jenkins NFS的SC创建参考:2.《DevOps》系列K8S部署CICD流…...

[SAP ABAP] 创建数据库视图和维护视图
数据准备 学校表(ZDBT_SCH_437) 学生表(ZDBT_STU_437) 学校表(ZDBT_SCH_437)与学生表(ZDBT_STU_437)字段 学校表(ZDBT_SCH_437)与学生表(ZDBT_STU_437)行数据明细 1.创建数据库视图 使用SE11创建数据库视图 填写视图名称ZV_DATABASEV_437,点击创建按钮 选择数据库视…...

【最快最简单的排序 —— 桶排序算法】
最快最简单的排序 —— 桶排序算法 桶排序是一种排序算法,其工作原理是将数据分到有限数量的桶子里,然后对每个桶内的元素进行单独排序,最后依次把各个桶中的记录列出来。桶排序的效率取决于映射函数的选择和桶的数量。 桶排序适用于数据分…...

AI时代,服务器厂商能否打破薄利的命运?
文|刘俊宏 编|王一粟 AI大模型正在引发新一轮的“算力焦渴”。 近日,OpenAI刚发布的o1大模型再次刷新了大模型能力的上限。对比上一次迭代的版本,o1的推理能力全方位“吊打”了GPT-4o。更优秀的能力,来自与o1将思维…...

2024年9月python二级易错题和难题大全(附详细解析)(二)
2024年9月python二级易错题和难题大全(附详细解析)(二) 第1题第2题第3题第4题第5题第6题第7题第8题第9题第10题第11题第12题第13题第14题第15题第16题第17题第18题第19题第20题第1题 1、以下代码的输出结果是() x = 12 + 3 * ((5 * 8) - 14) // 6 print(x) A、25.0 B、6…...

4.结构型设计模式 - 第1回:引言与适配器模式 (Adapter Pattern) ——设计模式入门系列
一、引言 在现代软件开发中,设计模式是帮助我们解决复杂问题的工具,它们提供了在常见场景下重用已验证解决方案的途径。而结构型设计模式主要关注类与对象之间的组合方式,旨在通过增强灵活性和降低耦合度来改进代码的结构。 本次讨论的是结…...

解决mybatis plus 中 FastjsonTypeHandler无法正确反序列化List类型的问题
由于是根据自动映射类型,我们设置的字段类型是List 也就是反序列化的时候也只是用 FastjsonTypeHandler中的 Override protected Object parse(String json) { return JSON.parseObject(json, type); } 反序列化方法,这是type为List 反序列后我们并没…...

MacOS安装homebrew,jEnv,多版本JDK
1 安装homebrew homebrew官网 根据官网提示,运行安装命令 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装后,bash会提示执行两条命令 (echo; echo eval "$(/opt/homebrew/b…...

【HTTP】认识 URL 和 URL encode
文章目录 认识 URLURL 基本格式**带层次的文件路径****查询字符串****片段标识符** URL encode 认识 URL 计算机中非常重要的概念,并不仅仅是在 HTTP 中使用。用来描述一个网络资源所处的位置,全称“唯一资源定位符” URI 是“唯一资源标识符“严格的说…...

【AI学习笔记】初学机器学习西瓜书概要记录(二)常用的机器学习方法篇
初学机器学习西瓜书的概要记录(一)机器学习基础知识篇(已完结) 初学机器学习西瓜书的概要记录(二)常用的机器学习方法篇(持续更新) 初学机器学习西瓜书的概要记录(三)进阶知识篇(待更) 文字公式撰写不易&am…...

[SDX35+WCN6856]SDX35 + WCN6856 默认增加打包wifi配置hostapd_24g.conf和hostapd_5g.conf操作方法
SDX35 SDX35介绍 SDX35设备是一种多模调制解调器芯片,支持 4G/5G sub-6 技术。它是一个4nm芯片专为实现卓越的性能和能效而设计。它包括一个 1.9 GHz Cortex-A7 应用处理器。 SDX35主要特性 ■ 3GPP Rel. 17 with 5G Reduced Capability (RedCap) support. Backward compati…...