我需要为从抽象类继承的所有类连接一个 django 信号。有没有像
__on_inherit__
这样的神奇Python方法,它允许我在每次继承抽象类时运行信号连接代码?
更新:为了澄清起见,我需要在每个类上运行一次类评估代码,而不是每个实例/对象运行一次。
__init_subclass__
钩子,每次类被子类化时都会触发它。
它将使用第一个参数
cls
作为 new 子类(而不是原始父类)进行调用。
正如文档中所述,您甚至可以将任意参数从子类传递给钩子。
希望这对您有帮助。
编辑:这是通过 Python 3.6 版本中的 PEP 487 添加的。在早期的 python 版本中,不会调用此方法。
我们可以为此实施一个解决方案。首先,我们可以生成抽象模型的子类集,例如使用这个解决方案:
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)
对于 python >= 3.6,Terseus 已经提到了
__init__subclass__
ok。
对于较旧的 python 版本,挂钩类创建(我的意思是“创建新类对象”)的规范方法是使用自定义元类并覆盖
__new__
或 __init__
方法(这已被广泛记录,因此我不会发布示例)。