Django 2.1.3 文档-模型层-执行查询
执行查询
-- 译自官方文档+自己的理解 --
一旦你创建了 数据模型,Django就会自动为你提供一个数据库抽象API,让你可以创建,检索,更新和删除对象。本文档介绍了如何使用此API。有关所有各种模型查找选项的完整详细信息,请参阅 数据模型参考。
在本指南(以及参考文献)中,我们将使用以下模型,包含于Weblog应用程序中:
1.创建对象
为了在Python对象中表示数据库表数据,Django使用直观的系统:模型类表示数据库表,该类的实例表示数据库表中的特定记录。
要创建对象,请使用模型类的关键字参数对其进行实例化,然后调用save()
以将其保存到数据库中。
假设模型存在于文件中mysite/blog/models.py,这里有一个例子:
这会在幕后执行INSERT
SQL语句。在您明确调用save()之前,Django不会访问数据库。
save()方法没有返回值。
参见
save()采用了许多此处未描述的高级选项。有关save()完整的详细信息,请参阅文档 。
要在一条语句中创建和保存对象,请使用 create()方法。↑
2.保存对对象的修改
要保存对已存在于数据库中的对象的更改,请使用 save()。
给定已保存到数据库的一个Blog实例 b5,此示例更改其名称并更新其在数据库中的记录:
这会在幕后执行UPDATE
SQL语句。在您明确调用save()之前,Django不会访问数据库。
2.1 保存ForeignKey 和 ManyToManyField 字段
更新ForeignKey字段的手段与保存普通字段的方式完全相同 - 只需将正确类型的对象分配给相关字段即可。假设适当的Entry和Blog实例已经保存到数据库中,这个例子更新了一个Entry实例entry的blog属性:
更新ManyToManyField方式略有不同 - 使用 add()字段上的方法向关系添加记录。此示例将Author实例 添加joe到entry对象:
要一次性添加多个ManyToManyField记录,请在调用add()中包含多个参数 ,如下所示:
如果您尝试分配或添加错误类型的对象,Django会提醒你。
3.检索对象
要从数据库中检索对象,请在模型类上使用Manager构建一个 QuerySet。
QuerySet表示数据库中的对象集合。它可以有零个,一个或多个过滤器。过滤器根据给定的参数缩小查询结果范围。在SQL术语中,一个QuerySet就是SELECT语句,过滤器是限制子句,如WHERE
或LIMIT
。
你可以使用模型中的Manager获得QuerySet。每个模型至少有一个 Manager,默认情况下调用 objects。通过模型类直接访问它,如下所示:
注解
Managers 只能通过模型类访问而不是模型实例访问,以强制“表级”操作和“记录级”操作之间的分离。↑
这Manager模型是QuerySets的主要来源。例如,Blog.objects.all()
返回的QuerySet包含Blog数据库中所有的对象。
3.1 检索所有对象
从表中检索对象的最简单方法是获取所有这些对象。为此,请使用 Manager中的all()
方法:
all()方法返回数据库中所有Entry对象的一个 QuerySet集合。
3.2 使用过滤器检索特定对象
通过 all()返回的QuerySet描述数据库中的表中的所有对象。但是,通常,您只需要选择整个对象集的子集。
要创建此类子集,请优化初始的QuerySet,为其添加过滤条件。两种最常见的改进方法QuerySet是:
- **filter(kwargs)
返回QuerySet包含与给定查找参数匹配的新对象。 - **exclude(kwargs)
返回QuerySet包含与给定查找参数不匹配的新对象。
查找参数(**kwargs在上面的函数定义中)应采用下面的字段查找中描述的格式。
例如,要获取2006年的博客条目的QuerySet,请使用下面的filter():
使用默认的manager类,它与以下内容相同:
3.3 过滤器链
QuerySet经过过滤器细化后还是一个QuerySet,因此可以将过滤器链接在一起。例如:
初始的QuerySet是数据库中所有Entry对象,添加filter,然后exclude,然后是另一个filter。最终结果是QuerySet包含标题以“What”开头的所有条目,这些条目是在2005年1月30日和当天之间发布的。
3.4 使用过滤器的QuerySets是唯一的
每当你细化一个QuerySet,你就会得到一个全新的QuerySet,与以前的QuerySet没有任何关系。每个细化都会创建一个独立且不同的QuerySet,可以存储,使用和重用。
这三者QuerySets是分开的。第一个是QuerySet包含所有条目的, 其中包含以“What”开头的标题。第二个是第一个的子集,exclude排除了pub_date为今天以后的记录。第三个是第一个的子集,filter选择了pub_date为今天以后的记录。初始的QuerySet(q1)不受细化过程的影响。
3.4 QuerySets是惰性的
QuerySets是懒惰的 - 创建一个 QuerySet不涉及任何数据库活动的行为。可以一直叠加过滤器,Django将不实际运行查询,直到QuerySet被 计算。看看这个例子:
虽然这看起来像访问数据库3次,但事实上它访问数据库中一次,在最后一行(print(q))。通常,在QuerySet在“询问”它们之前,不会从数据库中获取结果 。执行此操作时,QuerySet通过访问数据库来计算 。有关何时进行计算的更多详细信息,请参阅 何时QuerySe进行计算。