Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 用一个接收器整合多个post_save信号_Django - Fatal编程技术网

Django 用一个接收器整合多个post_save信号

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

因此,我阅读了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(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