我可以在每次继承抽象类时运行代码吗?

问题描述 投票:0回答:3

我需要为从抽象类继承的所有类连接一个 django 信号。有没有像

__on_inherit__
这样的神奇Python方法,它允许我在每次继承抽象类时运行信号连接代码?

更新:为了澄清起见,我需要在每个类上运行一次类评估代码,而不是每个实例/对象运行一次。

python django
3个回答
5
投票

是的,确实有

__init_subclass__
钩子,每次类被子类化时都会触发它。

它将使用第一个参数

cls
作为 new 子类(而不是原始父类)进行调用。 正如文档中所述,您甚至可以将任意参数从子类传递给钩子。

希望这对您有帮助。

编辑:这是通过 Python 3.6 版本中的 PEP 487 添加的。在早期的 python 版本中,不会调用此方法。


2
投票

我们可以为此实施一个解决方案。首先,我们可以生成抽象模型的子类集,例如使用这个解决方案

def get_descendants(klass):
    gen = { klass }
    desc = set()
    while gen:
        gen = { skls for kls in gen for skls in kls.__subclasses__() }
        desc.update(gen)
    return desc

接下来我们可以迭代它,每次调用一个函数,例如:

for subclass in get_descendants(AbstractModel):
    # ... do something with that subclass
    pass

其中

AbstactModel
是您要从中派生子类的抽象模型。

您应该在加载应用程序时触发对此的评估,例如在 ready()

AppConfig
 方法 [Django-doc]
中。

这是非常罕见的,特别是对于后来创建新子类的模型。对于非常不常见的模型,无论如何都不是一个好主意,因为当您想要进行迁移时,这可能不起作用。

示例:向每个子类添加信号

例如,我们可以通过首先定义信号处理程序来向

AbstractModel
的每个子类添加信号:

def test_signal(sender, instance, **kwargs):
    print('{} is saved'.format(instance))

然后我们可以将它与每个子类连接:

from django.db.models.signals import post_save

for subclass in get_descendants(AbstractModel):
    post_save.connect(test_signal, sender=subclass)

2
投票

对于 python >= 3.6,Terseus 已经提到了

__init__subclass__
ok。

对于较旧的 python 版本,挂钩类创建(我的意思是“创建新类对象”)的规范方法是使用自定义元类并覆盖

__new__
__init__
方法(这已被广泛记录,因此我不会发布示例)。

© www.soinside.com 2019 - 2024. All rights reserved.