Django笔记九之model查询filter、exclude、annotate、order_by
在接下来四五篇笔记中,将介绍 model 查询方法的各个细节,为我们的查询操作提供各种便利。
本篇笔记将介绍惰性查找、filter、exclude、annotate等方法,目录如下:
- 惰性查找
- filter
- exclude
- annotate
- alias
- order_by
1、惰性查找
前面我们在介绍 Django 增删改查的时候,提到过他的惰性查找的规则。
也就是说普通的 filter 语句执行时,系统并不会去查询数据库,只有当我们真正使用里面的数据的时候,才会去查询数据库。
那么以下介绍几种,使用的时候会查询数据库的情况:
迭代
一个 QuerySet 是可迭代的,而且仅会在第一次迭代的时候查询数据库:
for e in Entry.objects.all():
print(e.headline)
切片
需要注意的是,使用 python 里的切片语法不会访问数据库,比如:
Entry.objects.all()[:3]
但是,如果使用 step 语法则会访问数据库,比如以下语句:
Entry.objects.all()[:10:2]
len()
当我们使用 len() 函数去获取一个 QuerySet 的长度时,会访问数据库,比如:
len(Entry.objects.all())
但是这种做法是不被推荐的,因为他会把 QuerySet 中的所有数据,都加载出来,然后计算长度。
如果想要获取总数量,我们会使用另一个函数,.count(),这个我们后面会提到。
list()
这个操作会强制查询数据库,然后将一个 QuerySet 转换成 python 里的 list。
entry_list = list(Entry.objects.all())
在一般情况下,是不推荐的,因为相对于 list 而言,QuerySet 可以执行的函数更多。
bool()
判断是否存在数据:
if Entry.objects.filter(headline='hunter'):
print('exists')
但是,在Django 里一般也不推荐,因为有更高效的用法,那就是使用 .exists() 函数,这个在后面会详细介绍。
2、filter()
filter 这个函数前面都有介绍,可以在其中添加符合筛选条件,也可以通过链式的形式来操作。
但是链式执行的用法是 and 逻辑,如果想要用 or 逻辑,可以使用 Q() 用法来连用,前面也简单介绍过。
3、exclude()
这个函数与 filter() 函数功能相反,是排除符合条件的数据。
4、annotate()
annotate 这个单词的意思是 注释,在 Django 里的用法是,通过对数据进行处理,比如一个表达式,或者是通过外键引入一个新的数据字段,或者是聚合出来一个结果(比如平均值,综合等),会在每一条返回的数据里面新增一个前面表达式的结果作为一个新的字段返回。
比如我们获取 Blog 这个 model 的时候,Entry 作为它的外键关系,我们可以获取关联了某条 Blog 的 Entry 的数量,并且作为新的字段添加到 Blog 里一起返回,其操作如下:
q = Blog.objects.annotate(number_of_entries=Count('entry’))
q[0].number_of_entries
5、alias()
alias() 的用法和 annotate 一样,都可以创建新的数据字段,但与 annotate() 不一样的是,其结果并不会作为一个字段返回,而是用于在使用的过程中做筛选,比如一个用法如下:
q = Blog.objects.alias(number_of_entries=Count('entry')).filter(number_of_entries__gt=1)
6、order_by()
对于 QuerySet 每次返回的结果,如果 Meta 里有 ordering 参数,使用见上一篇 Meta 的使用笔记,那么数据就会按照 ordering 的参数对数据进行排序后返回。
如果 Meta 里没有设置该参数,那么数据则会在有主键 id 的情况下按照 id 的顺序返回。
当然,我们也可以使用 order_by() 这个函数来对每一次搜索的数据进行排序的重写。
正序排序
比如我们想要对 Entry 这个 model 对于 pub_date 进行正序排序:
Entry.objects.filter(pub_date__year=2005).order_by('pub_date')
倒序排序
则可以在字段名前面加个 - 负号来操作:
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date')
多个字段进行排序
比如 对 pub_date 倒序排序,对 headline 正序排序,则是:
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
按照外键字段排序
比如 Entry 这个 model 需要按照外键 Blog 的 name 字段来排序,则通过外键字段+双下划线+排序字段来实现:
Entry.objects.order_by('blog__name')
如果我们在查询 Entry 的时候直接根据外键字段,也就是 blog 来排序,Django 会使用 Blog,也就是外键的默认排序(即在 Blog 的 model 的 Meta 里设置的 ordering 来排序),如果外键没有定义默认排序,则会根据主键 id 来排序。
比如说,我们的 Blog model,如果没有在 Meta 里设置默认的 ordering,那么,下面的语句:
Entry.objects.order_by('blog')
则会等价于:
Entry.objects.order_by('blog_id')
如果在 Blog 的 model 的 Meta 里有设置 ordering=['name'],那么则等价于:
Entry.objects.order_by('blog__name')
查询表达式调用 asc() 或者 desc() 方法:
Entry.objects.order_by(Coalesce('summary', 'headline').desc())
asc() 和 desc() 有 nulls_first 和 nulls_last 来控制 null 如何被排序,是放在最开始还是最后面。
忽略大小写排序
我们可以通过对字段进行小写处理来达到忽略大小写排序的目的:
Entry.objects.order_by(Lower('headline').desc())
不排序
如果是不想对数据进行任何排序,则可以直接调用 order_by() 函数,不添加任何参数即可。
Entry.objects.order_by()
不支持链式处理
需要注意的是,不同于 filter() 函数的链式操作,order_by() 是不支持链式操作的,每添加一次 order_by(),前面的排序都会被后面的覆盖。
Entry.objects.order_by('headline').order_by('pub_date')
以上语句则仅会根据 pub_date 进行排序,headline 的排序则会被忽略。
这个功能如果要验证,很简答,只需要打印出上述语句转换成的 SQL 语句即可。
如果查看 Django 的 QuerySet 转换的 SQL 代码,以前写过一篇博客,可以参考:https://blog.csdn.net/weixin_43354181/article/details/102881471
以上就是本篇笔记全部内容,接下来将要介绍的是 reverse、distinct、values、values_list 等用法。
本文首发于本人微信公众号:Django笔记。
原文链接:Django笔记九之model查询filter、exclude、annotate、order_by
如果想获取更多相关文章,可扫码关注阅读:

Django笔记九之model查询filter、exclude、annotate、order_by的更多相关文章
- 79.常用的返回QuerySet对象的方法使用详解: filter, exclude,annotate
返回新的QuerySet的常用方法: 1.filter: 将满足条件的数据提取出来,返回一个新的QuerySet 以下所使用的模型article,category,定义模型models.py文件中,示 ...
- Django笔记&教程 5-2 进阶查询——Queryset
Django 自学笔记兼学习教程第5章第2节--进阶查询--Queryset 点击查看教程总目录 Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-a ...
- Django学习路12_objects 方法(all,filter,exclude,order by,values)
Person.objects.all() 获取全部数据 def get_persons(request): persons = Person.objects.all() # 获取全部数据 contex ...
- Django的model查询操作 与 查询性能优化
Django的model查询操作 与 查询性能优化 1 如何 在做ORM查询时 查看SQl的执行情况 (1) 最底层的 django.db.connection 在 django shell 中使用 ...
- Django(九)模型:dj查询数据库的函数(方法)
一.查询函数 通过模型类.objects属性可以调用如下函数,实现对模型类对应的数据表的查询. 函数表 函数名 功能 返回值 说明 get 返回表中满足条件的一条且只能有一条数据. 返回值是一个模型类 ...
- Django(进阶篇)之model
Model 解析 Django的数据库,涉及相关操作时就是以下流程: 1.创建数据库,设计表结构和字段 2.使用Mysqldb来连接数据库,并编写数据访问层 3.业务逻辑层去调用数据访问层执行数据库操 ...
- Django中级篇之Model专题
ORM 就是用面向对象的方式去操作数据库的创建表以及增删改查等操作 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据 ...
- Django框架中的model(操作数据库)
什么是ORM ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复 ...
- Django模型层之字段查询参数及聚合函数
该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. 字段查询是指如何指定SQL WHERE子句的 ...
- django(6)model表语句操作、Form操作、序列化操作
1.model建表操作之创建索引.元数据 # 单表操作,创建表 class User(models.Model): name = models.CharField(max_length=32) ema ...
随机推荐
- FPGA串口 波特率的计数器值
开发板时钟为50Mhz, t为 20ns; xxx波特率时指每秒传xxx bit字节数据.也就是T=1/xxx; 再用T/t就可以得出波特率的计数周期了: 例如9600:T=1/96000=1.041 ...
- python使用openpyxl读取合并单元格的值(转)
目录问题:解决思路:问题:假设在test.xlsx的"Sheet1"工作表中,A1:D3区域的值如下:要求给定指定的行.列以及对应的工作表作为参数,能够正确解析合并单元格,获取指定 ...
- RabbitMq的部署(docker)和操作(python)详解
一.简介: RabbitMq 是实现了高级消息队列协议(AMQP)的开源消息代理中间件.消息队列是一种应用程序对应用程序的通行方式,应用程序通过写消息,将消息传递于队列,由另一应用程序读取 完成通信. ...
- 如何跳出forEach循环
for(let ii in this.listData){ console.log("提交前数据",ii) try{ this.listData[ii].forEach((el,i ...
- ESP32 环境搭建以及入门编程流程和体验-windows
本帖适合入门级人员,但同时欢迎新老读者批评指正. 某宝上买了个esp32,还有一本ESP32开发指南的书. 然后就是环境搭建.上面写的主要是linux上的,我在自己的orange pi pc开发板上搭 ...
- hdu: You Are the One(区间DP)
Problem Description The TV shows such as You Are the One has been very popular. In order to meet the ...
- 图模配置文件之 flow.json
flow.json文件是用来配置图模导入时,各种不同的图模导入时,分别应该使用哪个映射文件对模型进行处理.在不同地区使用不同的格式的图模文件时,需要修改flow.json中相关的配置,来适应相应的图模 ...
- K8s+Docker 学习笔记系列
学前知识 你需要掌握 Linux 的常用命令.你可以通过Linux 教程 来学习相关命令. Docker应用场景 Web 应用的自动化打包和发布. 自动化测试和持续集成.发布. 在服务型环境中部署和调 ...
- Linux(CentOS)安装脚本
此文以CentOS为例,乌班图的是有区别的,请参照https://www.cnblogs.com/takako_mu/p/11725733.html. 安装.Net Core (能访问外网的情况下采用 ...
- MSSQL SQL SERVER 2008 使用RowNumber()分页查询并获取总行数 附达梦数据库
参数:pages:要查询的页码(要查询第几页):pageNum:要查询的行数(每页要查多少行):适用于使用多表查询,不以固定的实体类保存结果,如使用 List<Map<String, Ob ...