在控制器上调用方法返回查询集(QuerySet)。
查询经过过滤器筛选后返回新的查询集,所以可以写成链式调用

链式查询

QuerySet 支持链式查询

Author.objects.filter(name__contains="WeizhongTu").filter(email="tuweizhong@163.com")
Author.objects.filter(name__contains="Wei").exclude(email="tuweizhong@163.com")
 
# 找出名称含有abc, 但是排除年龄是23岁的
Person.objects.filter(name__contains="abc").exclude(age=23)

查询方法汇总

方法 说明
all() 返回所有数据
filter() 返回符合条件的数据
exclude() 过滤掉符合条件的数据
order_by() 排序
values() 一条数据就是一个字典,返回一个列表
get() 返回一个满足条件的对象
如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常
如果找到多个,会引发模型类.MultiObjectsReturned异常
first() 返回查询集的第一个对象。隐藏BUG:可能会出现first、last获取到的是相同的对象。
last() 返回查询集的最后一个对象。隐藏BUG:可能会出现first、last获取到的是相同的对象。
count() 返回当前查询集的个数
exist() 判断查询集中是否有数据,有数据返回True,否则返回False

隐藏BUG的解决办法:

  • 显式,手动写排序规则

查询集的切片操作

限制查询集,可以使用切片操作。等同于SQL中的limitoffset

切片区间:左闭右开Django切片的索引不能是负数,否则会报错。

Person.objects.all()[:10] 切片操作,前10条
Person.objects.all()[-10:] 会报错!!!
 
# 1. 使用 reverse() 解决
Person.objects.all().reverse()[:2] # 最后两条
Person.objects.all().reverse()[0] # 最后一条
 
# 2. 使用 order_by,在栏目名(column name)前加一个负号
Author.objects.order_by('-id')[:20] # id最大的20条

来自https://code.ziqiangxuetang.com/django/django-queryset-api.html

SQL查询语句中的 limit 与 offset 的区别:

limit y 分句表示: 读取 y 条数据

limit x, y 分句表示: 跳过 x 条数据,读取 y 条数据

limit y offset x 分句表示: 跳过 x 条数据,读取 y 条数据

查询集的缓存

查询集的缓存:每一个查询集都包含一个缓存,来最小化对数据库的访问

在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存,并返回查询结构,以后的查询直接使用查询集的缓存。

我们在写filter()、exclude()、all()都不会真正去查数据库,只有我们在迭代结果集,或者获取单个对象属性时,它才会查询数据库。

这种查询方式也叫懒查询,为了优化结构和查询。