Django听众没有听到信号

时间:2015-01-11 08:59:22

标签: python django django-signals

我正在尝试在激活时保存用户配置文件(而不是在用户创建时),但是侦听器不会调用create_user_profile()。收听者位于 models.py

from registration.signals import user_activated
from mysite.signals import create_user_profile

user_activated.connect(create_user_profile, sender=User)

我正在使用django-registration-redux。我没有在注册过程中覆盖任何内容。在 registration / signals.py 中,信号为:

user_activated = Signal(providing_args=["user", "request"])

registration / default / views.py 中有以下功能:

def activate(self, request, activation_key):
    """
    Given an an activation key, look up and activate the user
    account corresponding to that key (if possible).

    After successful activation, the signal
    ``registration.signals.user_activated`` will be sent, with the
    newly activated ``User`` as the keyword argument ``user`` and
    the class of this backend as the sender.

    """
    activated_user = RegistrationProfile.objects.activate_user(activation_key)
    if activated_user:
        signals.user_activated.send(sender=self.__class__,
                                    user=activated_user,
                                    request=request)

在PyCharm中,我在调用send()的最后一行放置了一个断点。当用户被激活时,执行在该断点处暂停,并从那里继续执行而没有错误消息。就像听众不在那里一样。

2 个答案:

答案 0 :(得分:1)

可能是发件人应该是User类:

signals.user_activated.send(sender=activated_user.__class__,
                            user=activated_user,
                            request=request)

答案 1 :(得分:1)

alecxe给出的答案是公认的答案。

我只是添加了这个答案来帮助像我这样的新手理解这里发生的事情,并提供一个替代解决方案来更改监听器而不更改包代码。

感谢一百万人给@alecxe这个答案。这是关键,最终帮助我围绕这个过程。在这种情况下,文档对我没什么帮助,似乎很多其他人也对信号有困难。

关键是sender元组中的send()必须与sender元组中的connect()匹配。

在这种情况下,发件人没有问题。问题是我的听众正在倾听正确的信号,但对于错误的发送者。更改send()元组工作,但我宁愿修复我的破坏的监听器,而不是修改注册包中的发件人。由于我的经验不足,我不知道sender=self.__class__在输出时会出现的情况。使用PyCharm和断点,我得到了答案。

我详细说明了我的做法,以防万一有人可以从中受益。

使用alexce的答案,我的信号监听器正在工作,所以我能够在create_user_profile()内放置一个断点。当信号仍然在内存中时暂停程序。此时,可以在调试器的变量列表中看到该信号。

我在 signals.py 中的'check_signal' args中添加了Signal

user_activated = Signal(providing_args=["user", "request", "check_signal",])

...然后将self.__class__添加回send()来电:

signals.user_activated.send(sender=activated_user.__class__,
                            user=activated_user,
                            request=request,
                            check_signal=self.__class__)

调试时,check_signal的值为<registration.backends.default.views.ActivationView>

因此,在不修改发件人的情况下修复我的监听器的解决方案是首先恢复 registration / signals.py 中的原始代码:

user_activated = Signal(providing_args=["user", "request"])

...并恢复 registration / default / views.py 中的代码:

signals.user_activated.send(sender=self.__class__,
                            user=activated_user,
                            request=request)

...最后,修复 models.py

中的监听器
from registration.backends.default.views import ActivationView
from registration.signals import user_activated
from mysite.signals import create_user_profile

user_activated.connect(create_user_profile, sender=ActivationView)

可能有一种方法可以在不必导入ActivationView的情况下执行此操作,但我不确定。它确实以这种方式工作。对于使用django-registration-redux和简单(无电子邮件)配置的任何人,唯一的区别是from registration.backends.simple.views import RegistrationView,监听器将是user_registered.connect(create_user_profile, sender=RegistrationView)

如果有人好奇,这里的代码来自 mysite / signals.py

def create_user_profile(sender, user, **kwargs):
    """
    When user is activated, create the UserProfile. Prevents dead profiles
    from registered users who never activate.
    """
    from mysite.models import UserProfile

    UserProfile(user=user).save()

我花了好几天的疯狂和绝望,获得了这七条小代码背后的逻辑。我希望这可以拯救别人免受这种压力。