在控制器上调用方法返回查询集(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中的limit
、offset
。
切片区间:左闭右开。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()都不会真正去查数据库,只有我们在迭代结果集,或者获取单个对象属性时,它才会查询数据库。
这种查询方式也叫懒查询
,为了优化结构和查询。