Django的Manager和QuerySet

2021-10-20 17:00:12 浏览数 (1)

Django的Manager和QuerySet

要从数据库检索对象,需要通过模型类的 Manager 构建一个 QuerySet。换言之,models,manager和queryset是我们和数据库交互必须的三个东西。 models本身没有什么需要多说的,Django 使用了一套直观的系统:一个模型类代表一张数据表,一个模型类的实例代表数据库表中的一行记录。

模型类的save方法可以插入,更新,删除数据。那么是否可以查询数据呢?实际上由于“一个模型类的实例代表数据库表中的一行记录”,因此模型类的实例是不能起到查询数据的功能。

Manager

因此,我们要从数据库检索到数据,ORM就必须提供相应的方法。在Django中,模型的Manager提供了接口,它赋予了 Django 模型操作数据库的能力。默认情况下,Django 为每个模型类添加了一个名为 objects 的 Manager。

不过,若你想将 objects 用作字段名,或想使用 objects 以外的 Manager 名字,就要在模型基类中重命名。要为指定类重命名 Manager,在该模型中定义一个类型为 models.Manager 的属性。例如:

代码语言:javascript复制
from django.db import models

class Person(models.Model):
    #...
    people = models.Manager()   # 自定义名为people的管理器

使用这个实例模型时, Person.objects 会产生一个 AttributeError 异常,而 Person.people.all() 会返回包含所有 Person 对象的列表。

一般而言,我们是不需要自定义manager的。除非以下两种情况:

  1. 添加额外的 Manager 方法;
  2. 修改 Manager 返回的原始 QuerySet。

有关如何自定义Manager,在Django管理器中有详细说明。

QuerySet

一个 QuerySet 代表来自数据库中对象的一个集合。它可以有 0 个,1 个或者多个 filters。

可以根据给定参数缩小查询结果量。在 SQL 的层面上, QuerySet 对应 SELECT 语句,而filters对应类似 WHERE 或 LIMIT 的限制子句。

如前所述,你能通过模型的 Manager 获取 QuerySet。每个模型至少有一个 Manager,默认名称是 objects。

需要注意的是Managers 只能通过模型类访问,而不是通过模型实例,目的是强制分离 “表级” 操作和 “行级” 操作。

什么时候QuerySet被执行?

在Django的文档中,明确的告诉了开发者,什么时候QuerySet被执行。因为这影响到SQL执行效率。在这里简要的说明一下,例如下面一段代码:

代码语言:javascript复制
>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

这段代码看起来好像是做了3次数据库查询,但是实际上并不是。实际只在最后一步print(q)的时候,做了一次数据库查询。因此,通常我们在返回JsonResponse的时候,需要list()函数来强制QuerySet做数据库操作。

细节

代码语言:javascript复制
1. 使用len()函数求QuerySet的长度,比起使用QuerySet的count()方法效率要低一些,count()方法实际对应于数据库的聚合函数COUNT,它是数据库层面的操作,而非python。

2. 同理,如果只想知道一个是否存在,可以使用QuerySet的 exences()方法,这比查询出对象本身更高效一些。

3. QuerySet可以被切片,但是不能使用负数索引。使用负数索引会抛出异常:AssertionError: Negative indexing is not supported.

QuerySet 类具有两个可用于自省的公开属性:

可以返回QuerySet对象的QuerySet方法

前文所述的看起来做了3次SQL查询,实际上只有一次。之所以能够实现这样的操作,那是因为上述的方法本身返回的对象依旧是QuerySet对象,而非其它。下面介绍一下常用的可以返回QuerySet对象的QuerySet方法

不能返回QuerySet对象的QuerySet方法

下面介绍一些常用的不能返回QuerySet对象的QuerySet方法。

字段查找

由于字段查询非常多,也非常常用,本文不进行说明。请直接参考Django字段查询

参考资料:

  1. 执行查询
  2. QuerySet API参考
  3. 管理器

0 人点赞