Django4.0 管理器-自定义管理器和模型继承
下面是Django如何处理自定义管理器和模型继承:
- 基类的管理器总是被子类以 Python 的普通名称解析顺序继承(子类上的属性会覆盖所有父类上的同名属性;直接父类会覆盖更上一级的,以此类推)。
- 如果没有在模型或其父类申明管理器,Django 会自动创建
objects
管理器。 - 一个类的默认管理器要么由
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()