Django 管理器的顺序影响哪些函数?

2 投票
2 回答
1282 浏览
提问于 2025-04-16 22:18

我看了大部分文档,也在StackOverflow上查了一些资料,但还是找不到我想要的答案。先给你看看代码。

# Manager
class ActiveManager(models.Manager):
    def get_query_set(self):
        return super(ActiveManager, self).get_query_set().filter(is_active=True)
# Model
class ModelA(models.Model):
    # ...
    is_active = models.BooleanField()
    objects = ActiveManager()
    all_objects = models.Manager()

在我玩代码的时候,我发现如果我这样写,并使用 get_object_or_404(),那么它会先用 ActiveManager 来查找所有活跃的记录,然后返回和我的查询相关的那条记录。不过,如果我把管理器的顺序调换一下:

class ModelA(models.Model):
    # ...
    all_objects = models.Manager()
    objects = ActiveManager()

那么它就会使用默认的管理器,这里是 all_objects 来进行查询。我想知道这个顺序的变化会影响到哪些其他功能。

补充一下:我明白类中找到的第一个管理器会成为默认管理器,但我想知道具体有哪些功能会使用这个默认管理器(比如 get_object_or_404)。

2 个回答

0

这影响很多事情。管理器的默认名称是 objects,这只是一个默认值,并不是必须的。如果你在模型定义中没有包含 objects,而是把管理器定义为 all_objects,那么 ModelA.objects 就不存在了。Django 只是给模型分配了一个默认的管理器,如果模型中没有其他管理器,并且你自己没有定义 objects

总之,Django 会把模型中定义的第一个管理器称为“默认管理器”,并在需要引用模型的管理器时使用这个“默认”管理器(因为它不能简单地使用 objects,因为 objects 可能没有被定义)。

一个简单的规则是,Django 应该使用的标准管理器(也就是说,最常用的管理器)应该是第一个定义的,不管它是分配给 objects 还是其他名称。其他的管理器应该在它之后定义。

3

这里是文档中相关的内容:“如果你使用自定义的 Manager 对象,请注意,Django 遇到的第一个 Manager(按照在模型中定义的顺序)有一个特殊的地位。Django 将类中定义的第一个 Manager 视为“默认” Manager,而 Django 的多个部分(包括 dumpdata)将专门使用这个 Manager 来处理该模型。因此,谨慎选择默认管理器是个好主意,以避免重写 get_query_set() 后无法获取你想要处理的对象”

如果你查看 get_object_or_404 的实现方式,你会发现它使用了模型的 _default_manager 属性,这就是 Django 用来指代第一个遇到的管理器的方式。(据我所知,所有 Django 的内部工作都是这样 -- 它们从不使用 Model.objects 等,因为你不应该假设默认管理器就叫 objects

撰写回答