用一个接收器合并多个 post_save 信号

所以我读了 Django 的源代码(后1.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(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@接收器修饰器功能,有没有更好的方法来做到这一点?

29317 次浏览

您可以跳过 model_name,然后连接到 post _ save 的所有模型。然后,你可以过滤,如果你在正确的模型在处理程序:

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 文件默认情况下,接收方不需要连接到特定的发送方,所以您描述的是默认的 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):
...

你可以使用 @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