通过模型方法上的装饰器发出 Django 信号?
我正在尝试做类似这些建议的信号装饰器之类的事情。除了有一个将装饰方法连接到信号的装饰器(将信号的发送者作为装饰器的参数)之外,我还想在类方法上使用装饰器。
我想像这样使用装饰器:
class ModelA(Model):
@connect.post_save(ModelB)
@classmethod
def observe_model_b_saved(cls, sender, instance, created, **kwargs):
# do some stuff
pass
装饰器是:
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
我这样做时得到的错误是:
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.
我猜问题是 @classmethod
返回一个不可调用的类方法对象。我不太明白 classmethod
在底层是如何工作的,但我从 此参考页面表明类方法对象在从类访问之前不会转换为可调用对象,例如ModelA.observe_model_b_saved
。有什么方法可以(1)将我的方法定义为模型上的类或实例方法,(2)直接在方法定义上使用装饰器将其连接到信号?谢谢!
I'm trying to do something like these proposed signal decorators. In addition to having a decorator that connects the decorated method to a signal (with the signal's sender as an argument to the decorator), I would like to use the decorator on class methods.
I'd like to use the decorator like so:
class ModelA(Model):
@connect.post_save(ModelB)
@classmethod
def observe_model_b_saved(cls, sender, instance, created, **kwargs):
# do some stuff
pass
The decorator is:
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
The error I get when I do this is:
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.
I guess the problem is that @classmethod
returns a class method object which is not callable. I don't really understand how classmethod
works under the hood, but I surmise from this reference page that the class method object is not translated into a callable until it is accessed from the class, e.g., ModelA.observe_model_b_saved
. Is there any way that I can both (1) define my method as a class or instance method on a model, and (2) connect it to a signal using a decorator directly on the method definition? Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你能把它改为@staticmethod吗?这样,您只需交换装饰器的顺序即可。
您必须通过全名引用该类,而不是传递 cls 参数,但这将允许您保持类似的代码组织。
Could you make it a @staticmethod instead? That way, you can just swap the order of the decorators.
You'd have to refer to the class by full name instead of getting passed the cls argument, but this would allow you to keep a similar code organization.
从您的示例代码中尚不清楚,所以我会问信号监听器是否实际上必须是
@classmethod
?即常规方法可以吗(如果您仍然需要访问类本身,则使用 self.__class__ )?它是否需要是一个方法(你可以只使用一个函数)吗?另一种选择可能是使用第二种方法来监听信号并将调用委托给
@classmethod
:It's not clear from your example code, so I'd be asking if the signal listener actually has to be a
@classmethod
? I.e. Will a regular method do (and then useself.__class__
if you still need to access the class itself)? Does it need to be a method at all (can you just use a function)?Another option might be to use a second method to listen to the signal and delegate the call to the
@classmethod
:根据马特的回答,@staticmethod 技巧对我有用。您可以使用字符串非具体地引用模型。
Based off of Matt's answer, the @staticmethod trick worked for me. You can use a string to reference a model non-concretely.