【问题标题】:Possible to change order of Django signals?可以更改 Django 信号的顺序吗?
【发布时间】:2012-04-18 13:00:00
【问题描述】:

我在用户注册时发送了 2 个信号,socialauth_registered 和 post_save。我希望 socialauth_registered 在 post_save 之前,因为它会影响 post_save 触发的功能。

这可能吗? (如果是,怎么办?!)

我不确定什么是相关的,但我有:

from django.contrib.auth.models import User
from social_auth.signals import socialauth_registered, pre_update
from django.db.models.signals import post_save

<ALL OF MY MODELS>

def create_user_profile(sender, instance, created, **kwargs):
    do some stuff

def create_social_profile(sender, user, response, details, **kwargs):
    do other stuff

socialauth_registered.connect(create_social_profile, sender=None)
post_save.connect(create_user_profile, sender=User)

【问题讨论】:

    标签: django signals django-signals


    【解决方案1】:

    我不肯定,但我会说这是值得怀疑的。更重要的是,信号背后的想法是它们应该是原子的。信号处理程序应该响应信号而不应该关心其他信号。依赖两个不相关信号的顺序(例如,显然您可以依赖 pre_save 和 post_save 的顺序)通常是不安全的。因此,即使我对您的问题没有明确的答案,我也会提供建议,您应该仔细考虑设计。

    【讨论】:

    • 感谢您的建议。我最终放弃了信号的想法,并尝试了一种绝对优越的不同方法。虽然你没有明确回答这个问题,但你告诉我这不是要问的正确问题,这可能是我能得到的最好答案!
    【解决方案2】:

    您是否考虑过使用一种调用 create_social_profile 和 create_user_profile 的信号。也许您可以将此信号附加到 post_save?

    【讨论】:

    • 很遗憾没有。每次创建用户对象时都会触发 post_save,而仅当用户通过第 3 方注册时才会触发 socialauth_registered。对于普通用户,我们确认电子邮件,这对于 socialauth 用户是不必要的,因此我们希望防止这种情况发生。理想情况下,常规注册会触发 post_save,社交注册会触发 socialauth_registered。
    【解决方案3】:

    不,您不能更改信号的执行顺序。

    已提出信号优先级,但核心开发者表示不会实现此功能:

    https://code.djangoproject.com/ticket/16547

    【讨论】:

    • 这应该是正确的答案。虽然标记的内容更多,但这是确定的。
    【解决方案4】:

    我知道这是一个非常古老的问题,但令我惊讶的是,我发现没有任何与处理程序订购的解决方法有关的任何信息。所以这里是调度器的一个子类,它实现了优先级。

    from django.dispatch import Signal as BaseSignal
    from django.dispatch.dispatcher import _make_id
    
    
    class Signal(BaseSignal):
    
        def connect(self, receiver, sender=None, weak=True, dispatch_uid=None, priority=50):
            if dispatch_uid is None:
                dispatch_uid = _make_id(receiver)
    
            inner_uid = '{0}{1}'.format(priority, dispatch_uid)
            super(Signal, self).connect(receiver, sender=sender, weak=weak, dispatch_uid=inner_uid)
            self.receivers.sort()
    

    虽然这对第三方应用程序没有帮助,但您可以使用此类创建自己的信号,并将它们附加到内置信号,从而允许您在自己的应用程序中订购处理程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 2011-03-29
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 2022-07-11
      • 1970-01-01
      相关资源
      最近更新 更多