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

时间:2019-06-27 08:45:20

标签: python django

我需要为从抽象类继承的所有类连接一个django signal。是否存在像__on_inherit__这样的魔术python方法,该方法使我每次继承抽象类时都可以运行信号连接代码?

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

3 个答案:

答案 0 :(得分:3)

是的,确实有[__init_subclass__] [1]钩子,每次类被子类化时都会触发。

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

希望这对您有所帮助。

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

[1] https://docs.python.org/3/reference/datamodel.html#object.init_subclass

[2] https://www.python.org/dev/peps/pep-0487/

答案 1 :(得分:2)

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

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 是要从其派生子类的抽象模型。

在加载应用程序时,应该触发对此的评估,例如在AppConfig的{​​{3}}中。

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

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

例如,我们可以通过首先定义信号处理程序将信号添加到 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 :(得分:2)

对于python> = 3.6,Terseus已经提到了__init__subclass__的确定。

对于较旧的python版本,钩入类创建的规范方法(我的意思是“创建新的类对象”)是使用自定义元类并覆盖__new____init__方法(这已被广泛记录,因此我将不发布示例)。