django进阶之条件查询FQ查询

条件查询

可以通过双下划线方式进行一些条件查询(以 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 特点
  1. 可迭代
    通过 for 循环读取每一行对象
  2. 支持切片
    通过类似列表的切片功能处理数据
    1
    2
    3
    4
    5
    6
    7
    obj_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
9
Andy 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 实践
  1. QuerySet 是惰性的,使用的时候添加过滤条件
  2. 要真正从数据库获取数据,可以遍历 queryset 或者使用 if queryset ,总是用到数据时就会执行 sql
  3. queryset 具有 cache。当你遍历 queryset 时,所有匹配的记录从数据库获取,然后转换成 django 的 model,这被称为执行。这些 model 会保存在 queryset 的 cache 中,这样如果你再次遍历这个 queryset,不需要重复运行通过的查询
  4. 简单的使用 if 语句进行判断也会完全执行整个 queryset 将数据放入 cache,当不需要这些数据时,为了避免这个,可以用 exists() 方法检查是否有数据
  5. queryset 非常巨大时, cache 会成为问题。成千上万的数据装入内存很浪费,可能造成程序崩溃,为避免在遍历数据时候产生 queryset cache,可以使用 iterator() 方法来获取数据,处理完数据就将其丢弃。
  • 总结
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
    使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能会造成额外的数据库查询

    F查询

    主要针对数字进行处理
    例如:下面是针对 userinfo 表中的 password 字段都加 1000
    对于可以转换成 int 格式的,直接加 1000, 不能转换成 int 格式的,该字段会直接更新成 1000
    1
    2
    from 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")

Recommended Posts