Django Signal via Decorator on Model Method?
我正试图做一些类似于这些被提议的信号装饰器的事情。除了有一个将修饰方法连接到信号的修饰器(信号的发送者作为修饰器的参数),我还想在类方法上使用修饰器。
我想用这样的装饰:
1 2 3 4 5 6 7 | class ModelA(Model): @connect.post_save(ModelB) @classmethod def observe_model_b_saved(cls, sender, instance, created, **kwargs): # do some stuff pass |
装饰师是:
1 2 3 4 5 6 | from django.db.models import signals def post_save(sender): def decorator(view): signals.post_save.connect(sender=sender, receiver=view) return view return decorator |
当我这样做时,我得到的错误是:
1 2 | File"/Library/Python/2.6/site-packages//lib/python2.6/site-packages/django/dispatch/dispatcher.py", line 78, in connect AssertionError: Signal receivers must be callable. |
我想问题是
可以改为@staticmethod吗?这样,您就可以交换装饰师的订单。
1 2 3 4 5 6 7 | class ModelA(Model): @staticmethod @connect.post_save(ModelB) def observe_model_b_saved(sender, instance, created, **kwargs): # do some stuff pass |
您必须用全名引用类,而不是传递cls参数,但这将允许您保持类似的代码组织。
从您的示例代码中还不清楚,所以我会问信号监听器实际上是否必须是一个
另一种选择可能是使用第二种方法来监听信号并将调用委托给
1 2 3 4 5 6 7 8 9 10 | class ModelA(Model): @classmethod def do_observe_model_b_saved(cls, sender, instance, created, **kwargs): # do some stuff pass @connect.post_save(ModelB) def observe_model_b_saved(self, sender, instance, created, **kwargs): self.do_observe_model_b_saved(sender, instance, created, **kwargs) |
根据马特的回答,@staticmethod技巧对我很有效。可以使用字符串非具体地引用模型。
1 2 3 4 5 6 | class Foo(Model): @staticmethod @receiver(models.signals.post_save, sender='someappname.Foo') def post_save(sender, instance, created, **kwargs): print 'IN POST SAVE', sender, instance.id, created |