Django4 中文入门教程 Django4.0 管理器-自定义管理器和模型继承

2024-02-25 开发教程 Django4 中文入门教程 匿名 6

下面是Django如何处理自定义管理器和模型继承:

  1. 基类的管理器总是被子类以 Python 的普通名称解析顺序继承(子类上的属性会覆盖所有父类上的同名属性;直接父类会覆盖更上一级的,以此类推)。
  2. 如果没有在模型或其父类申明管理器,Django 会自动创建 ​objects ​管理器。
  3. 一个类的默认管理器要么由 ​Meta.default_manager_name​ 指定,要么是模型中申明的第一个管理器,或者是直接父模型的默认管理器。

如果您想通过抽象基类在一组模型上安装自定义管理器,但仍能自定义默认管理器,这些规则提供了必要的灵活性。例如,假设有此基类:

class AbstractBase(models.Model):
# ...
objects = CustomManager()
class Meta:
abstract = True

如果您在子类中直接使用这一点,如果您在基类中没有声明任何管理器,那么 ​objects将是默认的管理器:

class ChildA(AbstractBase):
# ...
# This class has CustomManager as the default manager.
pass

如果您想继承 ​AbstractBase​,但提供不同的默认管理器,则可以在子类上提供该默认管理器:

class ChildB(AbstractBase):
# ...
# An explicit default manager.
default_manager = OtherManager()

这里的 ​default_manager ​是默认的。 ​objects ​管理器仍然可用,因为它是继承的,但没有被当做默认管理器。
最后,对于这个示例,假设您想要向子类中添加额外的管理器,但是仍然使用来自 ​AbstractBase ​的默认管理器。您不能直接在子类中添加新的管理器,因为这将覆盖默认管理器,并且您还必须显式地申明来自抽象基类的所有管理器。解决方案是将这个管理器放到另一个基类中,并在默认管理器 之后 将其引入继承层次结构:

class ExtraManager(models.Model):
extra_manager = OtherManager()
class Meta:
abstract = True
class ChildC(AbstractBase, ExtraManager):
# ...
# Default manager is CustomManager, but OtherManager is
# also available via the "extra_manager" attribute.
pass

请注意,虽然可以在抽象模型上定义自定义管理器,但不能使用抽象模型 调用 任何方法。即:

ClassA.objects.do_something()

上述是合法的,但如下会引发一个异常。这是因为管理器意在封装管理映射对象集合的逻辑。因为您不能拥有抽象对象的集合,所以管理抽象对象是没有意义的。如果您有适用于抽象模型的功能,则应该将该功能放在抽象模型的 静态方法 或 类方法 中:

AbstractBase.objects.do_something()