Django 用一个接收器整合多个post_save信号
因此,我阅读了Django源代码(Post1.5),您现在可以将多个信号注册到接收器函数:Django 用一个接收器整合多个post_save信号,django,Django,因此,我阅读了Django源代码(Post1.5),您现在可以将多个信号注册到接收器函数: def receiver(signal, **kwargs): """ A decorator for connecting receivers to signals. Used by passing in the signal (or list of signals) and keyword arguments to connect:: @receiver(po
def receiver(signal, **kwargs):
"""
A decorator for connecting receivers to signals. Used by passing in the
signal (or list of signals) and keyword arguments to connect::
@receiver(post_save, sender=MyModel)
def signal_receiver(sender, **kwargs):
...
@receiver([post_save, post_delete], sender=MyModel)
def signals_receiver(sender, **kwargs):
...
"""
... implementation code...
但是,我想将来自不同发送方的多个post_save信号注册到同一个函数中。现在,我只是打电话
post_save.connect(fn_name, model_name)
对于我拥有的每种型号。使用新的Django 1.5@receiver decorator功能是否有更好的方法实现这一点?您可以跳过
model\u name
,并在保存后连接到所有型号。然后,如果处理程序中的模型正确,则可以进行筛选:
post_save.connect(foo)
def foo(sender, **kwargs):
if sender not in [FooModel, BarModel]:
return
... actual code ...
或者,您可以根据模型中的字段进行筛选:
def foo(sender, **kwargs):
if not getattr(sender, 'process_by_foo', False):
return
... actual code ...
根据,默认情况下,接收器不需要连接到特定的发送方。所以您描述的是默认的Django功能
换句话说,要使用@receiver
装饰器实现这一点,只需在装饰器中指定发送者即可。例如:
@receiver(post_save) # instead of @receiver(post_save, sender=Rebel)
def set_winner(sender, instance=None, created=False, **kwargs):
list_of_models = ('Rebel', 'Stormtrooper', 'Battleground')
if sender.__name__ in list_of_models: # this is the dynamic part you want
if created: # only run when object is first created
... set the winner ...
这假设模型如下所示:
class Rebel(models.Model):
...
class Stormtrooper(models.Model):
...
class Battleground(models.Model):
...
您可以使用以下命令来执行此操作:
在其他型号的post_保存时,该接收器是否也会被调用?这可能会有很多电话…@nivcaner是的,这就是问题的目的:使用一个
post\u save
来监听多个服务器上的更改models@TylerHayes多个模型与所有模型不同models@DylanYoung对。答案被标记为已接受。如果提问者认为这不再是他们问题的最佳答案,欢迎他们更改。如果您将模型列表设置为{'rebel','stormtrooper'}
,则中的语句将是O(1)而不是O(N),这并不比现在接受的答案中的多个注册更复杂;此外,还可以在设置中定义或计算模型列表。因此,我对这一条竖起大拇指,谢谢你@Tyler Hayes!这应该是可以接受的答案,尽管它可以用定制的装饰器使它更干燥;然而,我认为在这种情况下,这将有损于清晰度。这个问题的最佳答案与@freethebees一致。这表明存在多个发送者。自定义装饰程序将隐藏该事实(如果只是暂时的)。所需的导入是来自django.dispatch import receiver的。
from django.dispatch import receiver
@receiver(post_save, sender=Model1)
@receiver(post_save, sender=Model2)
@receiver(post_save, sender=Model3)
def my_signal_handle(sender , **kwargs)
# some code here
def receiver_with_multiple_senders(signal, senders, **kwargs):
"""
Based on django.dispatch.dispatcher.receiver
Allows multiple senders so we can avoid using a stack of
regular receiver decorators with one sender each.
"""
def decorator(receiver_func):
for sender in senders:
if isinstance(signal, (list, tuple)):
for s in signal:
s.connect(receiver_func, sender=sender, **kwargs)
else:
signal.connect(receiver_func, sender=sender, **kwargs)
return receiver_func
return decorator