F 对象:让“阅读量>评论量”这种需求 1 行代码就能搞定 Q 对象:让 “并且、或者、非” 三种逻辑在 ORM 里一行搞定
【摘要】 F 对象:让“阅读量>评论量”这种需求 1 行代码就能搞定 Q 对象:让 “并且、或者、非” 三种逻辑在 ORM 里一行搞定 场景:运营同学提需求“把阅读量 大于 评论量的书找出来,再顺便把阅读量 大于评论量两倍 的也列出来。” 传统 SQL 写法-- 阅读量 > 评论量SELECT * FROM bookinfo WHERE read_count > comment_cnt;-- 阅读量...
F 对象:让“阅读量>评论量”这种需求 1 行代码就能搞定 Q 对象:让 “并且、或者、非” 三种逻辑在 ORM 里一行搞定
场景:运营同学提需求
“把阅读量 大于 评论量的书找出来,再顺便把阅读量 大于评论量两倍 的也列出来。”
传统 SQL 写法
-- 阅读量 > 评论量
SELECT * FROM bookinfo WHERE read_count > comment_cnt;
-- 阅读量 > 评论量 * 2
SELECT * FROM bookinfo WHERE read_count > comment_cnt * 2;
要写两条 SQL,还得自己算乘法。
Django ORM 写法:F 对象一行搞定
1. 引入 F
from django.db.models import F
2. 阅读量 > 评论量
BookInfo.objects.filter(read_count__gt=F('comment_cnt'))
# 返回 <QuerySet [<BookInfo: 雪山飞狐>]>
3. 阅读量 > 评论量 * 2
BookInfo.objects.filter(read_count__gt=F('comment_cnt') * 2)
F('comment_cnt') * 2
直接在 SQL 层完成乘法,不先拉数据到内存。
一句话记忆
-
F(‘字段名’) 代表数据库列本身
-
支持运算:
+ - * / %
-
无需 save,直接生成 SQL 条件
Q 对象:让 “并且、或者、非” 三种逻辑在 ORM 里一行搞定
场景引入
运营同学提了两个需求:
-
并且:把“阅读量大于 20 且 编号 < 3” 的书找出来。
-
或者:把“阅读量大于 20 或 编号 < 3” 的书找出来。
用原生 SQL 要写两段 WHERE … AND …
、WHERE … OR …
,Django 里却只要 Q 对象 一行完成。
1️⃣ 并且查询(AND)
写法 ①:链式 filter(最简单)
BookInfo.objects.filter(
read_count__gt=20,
id__lt=3
)
写法 ②:Q 对象显式 AND
from django.db.models import Q
BookInfo.objects.filter(
Q(read_count__gt=20) & Q(id__lt=3)
)
结果 | 解释 |
---|---|
只返回 同时满足 两个条件的记录 | & 就是 SQL 里的 AND |
2️⃣ 或者查询(OR)
BookInfo.objects.filter(
Q(read_count__gt=20) | Q(id__lt=3)
)
结果 | 解释 |
---|---|
只要满足 任意一个 条件即可返回 | ` |
3️⃣ 非查询(NOT)
把“编号 不等于 3” 的书排除掉:
# 写法 ①:exclude
BookInfo.objects.exclude(id=3)
# 写法 ②:Q 对象取反
BookInfo.objects.filter(~Q(id=3))
符号 | 含义 |
---|---|
~ |
逻辑 NOT,相当于 SQL 里的 NOT |
4️⃣ 混合逻辑:括号优先级
再升级需求:
“阅读量>20 且(编号<3 或 书名含‘剑’)”
BookInfo.objects.filter(
Q(read_count__gt=20) &
(Q(id__lt=3) | Q(name__contains='剑'))
)
Q 对象天然支持 括号级联,SQL 自动生成
()
保证优先级。
记忆口诀
-
并且
&
-
或者
\|
-
非
~
-
双下划线 + 运算符 永远不变
30 秒小练习
把下面空格补齐:
from django.db.models import Q
# 阅读量>50 或 编号<=2,但排除书名含“飞”的书
BookInfo.objects.filter(
Q(read_count__gt=50) | Q(id__lte=2)
).exclude(name__contains='飞')
答案已在代码里,直接复制即可跑通!
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)