【问题标题】:Django signals not working properlyDjango 信号无法正常工作
【发布时间】:2014-11-20 11:04:55
【问题描述】:

我正在尝试设置一个信号,以便在保存有效表单时运行一个函数来执行相关任务。

我的应用结构如下;

- events
    - helpers
        - __init__.py
        - status.py
    - models
        - signals
            - __init__.py
            - event.py
        - __init__.py
        - event.py
        - status.py
    - views
        - __init__.py
        - event.py

我认为需要在模型之前尽早导入信号,所以在models/__init__.py 的顶部我有from .signals import *

# views/event.py
class AddEventView(CreateView):
    """
    View for adding an Event.
    """
    model = Event
    form_class = EventForm
    success_url = reverse_lazy('events:all_events')

    def form_valid(self, form):
        self.object = form.save()

        signals.event_status.send(
            sender=None, request=self.request, event=self.object, status=None
        ) # Should the sender be self.object?

        return super(AddEventView, self).form_valid(form)

# signals/event.py
from django.dispatch import Signal
event_status = Signal(providing_args=["request", "event", "status"])

# helpers/status.py
from ..models import Status, StatusHistory
from ..models.signals import event_status


def create_status(sender, **kwargs):
    """
    Create a status for a given event.
    """
    event = kwargs['event']
    status = kwargs['status']
    creator = User.objects.get(pk=event.creator)
    try:
        current_status = StatusHistory.objects.filter(
            event=event).order_by('timestamp')[0]
    except IndexError:
        # Not sure what we're doing here yet.
        pass
    if not status:
        status = Status.objects.get(description=_("Submitted"))

    statushistory = StatusHistory.create(
        event=event,
        event_status=status,
        user=creator
    )
    statushistory.save()

event_status.connect(create_status)

我在 Pycharm 中运行调试服务器,在 create_status() 函数中有一个断点,它永远不会被命中。

我是不是执行错了?

【问题讨论】:

  • 我猜你知道他们应该是__init__.py而不是init.py

标签: django signals


【解决方案1】:

我发现了一个signal 不起作用的案例。

以下情况signal(pre_save, post_save) 不会发生。

Model.objects.filter(pk=pk).update(key=value)

批量模型函数不会发生信号。

【讨论】:

    【解决方案2】:

    我在一些项目中使用了信号,我总是将信号导入我的 Django APP 的__init__.py(与 settings.py、views.py、urls.py 相同的文件夹...)

    __init__.py

    import signals
    

    signals.py:

    from django.db.models.signals import post_save, pre_delete 
    from django.dispatch import receiver
    from my_project.models import *
    
    
    @receiver(post_save, sender=Modelname)  # Called after an object is saved
    def create_modelname(sender, **kwargs):
        obj = kwargs['instance']  # I get the object being saved here
        # ... Here I do whatever I want
    
    @receiver(pre_delete, sender=Modelname)  # Called before an object is deleted
    def delete_modelname(sender, **kwargs):
       obj = kwargs['instance']
       # ... Do whatever you need
    

    记住这 2 个导入:

    • from django.db.models.signals import post_save, pre_delete
    • from django.dispatch import receiver

    记得导入信号

    • 要导入您需要在项目的__init__.py 中添加import signals 的信号

    使用此代码,当创建或删除类 Modelname 的对象时,Django 会自动调用此函数。

    创建对象的接收者被称为after对象被创建,而被删除对象的接收者被称为before对象被删除。

    【讨论】:

    • 谢谢,我已经看到 receiver 装饰器在我一直在查看这个时使用过,并且过去使用 pre_save 等方法来缓存信号,以获得非常简单的信号。您可以使用该方法将自己的 kwargs 添加到 Signal 中吗?
    • 我想是的,你应该检查 Django 文档,看来你必须覆盖保存方法
    • 仅仅创建一个 signals.py 文件是不够的,这不会被 Django 自动导入......它只会工作,因为你从该文件的其他地方导入了代码中的信号确实由 Django docs.djangoproject.com/en/dev/topics/signals/… 导入
    • @Anentropic 我在至少 6 个项目中使用了信号,但没有一个项目在任何地方导入信号。管理信号的是 Django,当创建对象时,转到 signals.py。我并不是说你不能以不同的方式来做,我是说这种方式有效,至少对于 Django 1.5 和 Django 1.6
    • @Anentropic 你是对的,我正在检查我的文件并找到了导入,它在__init__.py 上,就像 tuto 说的那样
    【解决方案3】:

    我想也许你只需要导入你的helpers/status.py 例如models/__init__.py

    否则你的 event_status 信号被定义好,但信号处理程序 create_status 永远不会被 Django 连接

    如果您对该信号只有一个处理程序,则将其放在与信号定义相同的模块中可能是有意义的

    【讨论】:

    • 是的,我正在考虑移动它并将助手导入信号。我会试一试的。谢谢。
    猜你喜欢
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 2013-10-21
    • 2014-03-07
    • 2013-02-25
    • 2015-01-06
    相关资源
    最近更新 更多