检索对象
要从数据库检索对象,必须通过模型类的 Manager
构建一个 QuerySet
。 QuerySet
代表来自数据库中对象的一个集合
通过模型的 Manager
获取 QuerySet
。每个模型至少有一个 Manager
,默认名称是 objects
。
Manager
是模型的 QuerySet
s 主要来源。
-
检索全部对象
从数据库检索全部对象使用
Manager
中的all()
- all 返回数据库包含的所有
QuerySet
对象
all_entries = Entry.objects.all()
- all 返回数据库包含的所有
-
检索指定对象
检索指定对象使用过滤器
- filter 返回一个
QuerySet
,包含满足给定查询参数的对象。 - exclude 返回一个
QuerySet
, 包含不满足给定查询参数的对象
- filter 返回一个
-
检索单个对象
-
get 返回一个对象,并非
QuerySet
注意:
- 如果没有满足查询条件的结果, get() 会抛出一个 DoesNotExist 异常
- 如果不止一条记录满足查询条件时发出警告, 抛出 MultipleObjectsReturned
出于方便的目的,Django 提供了一种 pk 查询快捷方式, pk 表示主键 “primary key”。
示例 Blog 模型中,主键是 id 字段,所以这 3 个语句是等效的:
Blog.objects.get(id__exact=14) # Explicit form Blog.objects.get(id=14) # __exact is implied Blog.objects.get(pk=14) # pk implies id__exact
-
其他检索方法
- 返回
QuerySet
方法- annotate
- order_by
- reverse
- distinct
- values
- values_list
- dates
- datetimes
- none
- union
- intersection
- difference
- select_related
- prefetch_related
- extra
- defer
- only
- using
- select_for_update
- raw
- 不返回
QuerySet
方法- get
- create
- get_or_create
- update_or_create
- bulk_create
- bulk_update
- count
- in_bulk
- iterator
- latest
- earliest
- first
- last
- aggregate
- exists
- update
- delete
- as_manager
- explain
链式过滤器
过滤器可是链式地对数据库进行检索
官方示例:
Entry.objects.filter(
headline__startswith='What'
).exclude(
pub_date__gte=datetime.date.today()
).filter(
pub_date__gte=datetime.date(2005, 1, 30)
)
QuerySet 是惰性的
创建 QuerySet
并不会引发任何数据库活动, 直到要使用 QuerySet
的结果时才会从数据库中取出
QuerySet 切片
利用 Python 的数组切片语法将 QuerySet
切成指定长度。这等价于 SQL 的 LIMIT 和 OFFSET 子句
字段查询
字段查询关键字遵遵照 field__lookuptype=value
, 字段与查询类型以双下划线分割
官方示例:
Entry.objects.filter(pub_date__lte='2006-01-01')
其含义与 SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
相同
例外:
在 ForeignKey 中,可以指定以_id
为后缀的字段名官方示例:
Entry.objects.filter(blog_id=4)
若传入了无效的关键字参数,查询函数会抛出
TypeError
-
查询类型
- exact
- iexact
- contains
- icontains
- in
- gt
- gte
- lt
- lte
- startswith
- istartswith
- endswith
- iendswith
- range
- date
- year
- iso_year
- month
- day
- week
- week_day
- quarter
- time
- hour
- minute
- second
- isnull
- regex
- iregex
关系查询
关系查询用来查询JOIN关系,跨模型关系使用关联字段名,字段名使用双下划线分割
关系查询对关系模型也可以反向操作
官方示例:检索出所有的 Entry 对象,其 Blog 的 name 为 ‘Beatles Blog’
Entry.objects.filter(blog__name='Beatles Blog')
F 表达式
F
对象可以进行加、减、乘、除、求余和次方
使用 F
表达式必须导入 F
对象
from django.db.models import F
官方示例:
Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks'))
Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks') * 2)
Entry.objects.filter(rating__lt=F('number_of_comments') + F('number_of_pingbacks'))
Q 表达式
Q
对象能通过 & 和 | 操作符连接起来。 当操作符被用于两个 Q
对象之间时会生成一个新的 Q
对象。 它也可以被 ~
反转
使用 Q
表达式必须导入 Q
对象
from django.db.models import Q
官方示例:
Q(question__startswith='Who') | Q(question__startswith='What')
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
聚合查询
Django 提供了两种生成聚合的方法。
-
第一种方法是从整个
QuerySet
生成汇总值。通过在QuerySet
后添加aggregate()
子句来计算QuerySet
对象的汇总值ook.objects.all().aggregate(Avg('price')) ook.objects.aggregate(Avg('price'))
传递给
aggregate()
的参数描述了我们想要计算的聚合值,查询值以字典返回,聚合的参数可以有多个
aggregate()
是 QuerySet 的一个终端子句 -
使用 annotate() 子句可以生成每一个对象的汇总
注:
QuerySet
中的每一个对象将对指定值进行汇总。Book.objects.annotate(num_authors=Count('authors'))
annotate()
与 aggregate()
不同的是,annotate() 不是终端子句。annotate()
子句的返回的是 QuerySet
当使用 annotate()
组合多个聚合将产生错误的结果( yield the wrong results ),因为它使用连接(joins)而不是子查询,但对于Count
聚合可以使用 distinct
参数来避免
Book.objects.annotate(Count('authors', distinct=True), Count('store', distinct=True))
聚合函数位于 django.db.models
- 聚合函数
- Avg
- Count
- Max
- Min
- StdDev
- Sum
- Variance
注:聚合也可以参与过滤