条件查询
可以通过双下划线方式进行一些条件查询(以 userinfo 表示例)
查询 id 大于 1 且小于 5 的数据
1
models.UserInfo.objects.filter(id__lt=5, id__gt=1)
查询 id 在指定列表中的数据
1
models.UserInfo.objects.filter(id__in=[11, 22, 33])
查询 id 不包括在指定列表中的数据
1
models.UserInfo.objects.exclude(id__in=[11, 22, 33])
查询 name 中包含 ven 的数据
1
models.UserInfo.objects.filter(name__contains="ven")
查询 name 中包含 ven 的数据(大小写不敏感)
1
models.UserInfo.objects.filter(name__icontains="ven")
查询 id 在 1 和 2 之间的数据(效果类似于
between and
)1
models.UserInfo.objects.filter(id__range=[1, 2])
查询以指定字符串开头的数据
1
models.UserInfo.objects.filter(name__startswith="andy")
类似的查询istartswith
查询以指定字符串开头的数据,大小写不敏感endswith
查询以指定字符串结尾的数据iendswith
查询以指定字符串结尾的数据,大小写不敏感
惰性机制
查询结果返回的是一个queryset
,但它并不会马上执行 sql ,等到调用queryset
的时候才执行 sql 查询
- queryset 特点
- 可迭代
通过 for 循环读取每一行对象 - 支持切片
通过类似列表的切片功能处理数据1
2
3
4
5
6
7obj_li = models.UserInfo.objects.all() #返回结果为QuerySet list,可迭代
for item in obj_li:
print(item.name, item.username)
print(obj_li)
print(obj_li[1])
print(obj_li[1:3])
print(obj_li[::-1])
执行结果1
2
3
4
5
6
7
8
9Andy Andy
Bob Bob
Cinder Cinder
ddd ddd
多对多测试 test
<QuerySet [<UserInfo: Andy>, <UserInfo: Bob>, <UserInfo: Cinder>, <UserInfo: ddd>, <UserInfo: 多对多测试>]>
Bob
[<UserInfo: Bob>, <UserInfo: Cinder>]
[<UserInfo: 多对多测试>, <UserInfo: ddd>, <UserInfo: Cinder>, <UserInfo: Bob>, <UserInfo: Andy>]
前5行为迭代查询的结果
第6行为打印出的 obj_li ,结果为 QuerySet list
第7行为切片[1],取的QuerySet 中的第2个结果(列表索引从0开头是)
第8行为切片[1:3]
第9行为切片[::-1],其实就是倒序功能
- queryset 实践
- QuerySet 是惰性的,使用的时候添加过滤条件
- 要真正从数据库获取数据,可以遍历 queryset 或者使用 if queryset ,总是用到数据时就会执行 sql
- queryset 具有 cache。当你遍历 queryset 时,所有匹配的记录从数据库获取,然后转换成 django 的 model,这被称为执行。这些 model 会保存在 queryset 的 cache 中,这样如果你再次遍历这个 queryset,不需要重复运行通过的查询
- 简单的使用 if 语句进行判断也会完全执行整个 queryset 将数据放入 cache,当不需要这些数据时,为了避免这个,可以用 exists() 方法检查是否有数据
- queryset 非常巨大时, cache 会成为问题。成千上万的数据装入内存很浪费,可能造成程序崩溃,为避免在遍历数据时候产生 queryset cache,可以使用 iterator() 方法来获取数据,处理完数据就将其丢弃。
- 总结
queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能会造成额外的数据库查询F查询
主要针对数字进行处理
例如:下面是针对 userinfo 表中的 password 字段都加 1000
对于可以转换成 int 格式的,直接加 1000, 不能转换成 int 格式的,该字段会直接更新成 10001
2from django.db.models import F
models.UserInfo.objects.update(password=F("password")+1000)
Q查询
导入 Q 查询1
from django.db.models import Q
Q查询可以对关键字进行封装,从而更好的应用多个查询1
models.UserInfo.objects.filter(Q(username__contains="d")).all()
可以使用 &
,
|
操作符,当一个操作符用户用于两个 Q 对象,它产生一个新的 Q 对象&
,
表示与|
表示或1
models.UserInfo.objects.filter(Q(username="Cinder") | Q(password="3123"))
Q对象也可以用 ~
操作符放在前面表示否定,也可以否定和不否定的形式组合1
models.UserInfo.objects.filter(~Q(username="Andy") & Q(password="3123"))
Q对象可以和关键字查询一起使用,但Q对象放在关键字参数查询的前面
关键字参数和位置参数同时存在,位置参数应该在前1
models.UserInfo.objects.filter(Q(password="3123"), name__startswith="a")