【问题标题】:What is the difference between using django signals and calling a method?使用 django 信号和调用方法有什么区别?
【发布时间】:2021-12-17 15:10:18
【问题描述】:

我正在尝试实现一个功能,该功能在发布新文档记录时向所有员工记录发送通知。在模型中,我仍然需要导入接收器函数,因为我的发送器模型位于不同的项目中:

receiver 函数(位于项目中的不同应用程序中):

def new_document_version_published(sender, instance, **kwargs):
    print("New version of document published!")
    print(sender)
    print(instance)

    # Get all employees
    employees = []

    # Send notifications to employees
    buttons = [NotificationButton(button_text="New version of document", value="Ok", style="primary")]
    notifyUsers("A new version of the document has been published", buttons, employees, [])

发件人(位于项目中的不同应用程序中):

from django.db.models.signals import post_save
from api.views import new_document_version_published

    class DocumentVersion:
        ...
        def save(self, *args, **kw):
            if self.pk is not None:
                orig = DocumentVersion.objects.get(pk=self.pk)
                if orig.date_published != self.date_published:
                    print('date_published changed')
                    notify_employees()
                if orig.date_approved != self.date_approved:
                    print('date_approved changed')
            super(DocumentVersion, self).save(*args, **kw)
    
    def notify_employees():
        post_save.connect(new_document_version_published, sender=DocumentVersion)

我知道我的实现有问题,因为我不明白使用信号与仅导入和调用接收器函数之间有什么区别。感谢所有帮助!

【问题讨论】:

  • 信号用于文件helps decoupled applications get notified when actions occur elsewhere in the framework中的情况。当然你可以在每次调用动作时只导入接收函数,或者你只需​​要用信号写1次

标签: python django django-rest-framework signals


【解决方案1】:

有什么区别

调用函数使调用者依赖(或至少知道)接收函数,而使用 Django 信号使接收函数依赖于被调用的信号由它的调用者。

来自https://docs.djangoproject.com/en/3.2/topics/signals/

... 帮助解耦的应用程序在框架中其他地方发生操作时得到通知。简而言之,信号允许某些发送者通知一组接收者某些动作已经发生。当多段代码可能对相同的事件感兴趣时,它们特别有用。

何时使用 Django 信号

来自https://www.django-antipatterns.com/antipattern/signals.html

信号有各种各样的问题和无法预料的后果。 ...

通常最好避免使用信号。一个人可以实现很多逻辑没有信号。 ...

如果您想处理由第三方 Django 应用程序引发的事件,信号仍然是一个很好的解决方案。 ...

这种差异是什么样的

调用函数

预存:

# notify_employees()                                  # Replace this
new_document_version_published(self.__class__, self)  # with this

保存后:

class DocumentVersion(models.Model):
    ...
    def save(self, *args, **kw):
        orig = None  # .........  # Add this
        if self.pk is not None:
            orig = DocumentVersion.objects.get(pk=self.pk)
            if orig.date_published != self.date_published:
                print('date_published changed')
                # notify_employees()                              # Replace this
            if orig.date_approved != self.date_approved:
                print('date_approved changed')

        super(DocumentVersion, self).save(*args, **kw)

        if orig and orig.date_published != self.date_published:   # with this
            new_document_version_published(self.__class__, self)  #

使用 Django 信号

由于 Django 的 post_save 信号没有通过 orig,让我们使用自定义信号:

  1. 定义一个信号。
  2. 发送信号。
  3. 实现接收函数。
  4. 连接接收函数,通常是定义接收函数的地方。

保存后:

post_save_published = Signal()  # Add this


class DocumentVersion(models.Model):
    ...
    def save(self, *args, **kw):
        orig = None  # .........  # Add this
        if self.pk is not None:
            orig = DocumentVersion.objects.get(pk=self.pk)
            if orig.date_published != self.date_published:
                print('date_published changed')
                # notify_employees()                                        # Replace this
            if orig.date_approved != self.date_approved:
                print('date_approved changed')

        super(DocumentVersion, self).save(*args, **kw)

        if orig and orig.date_published != self.date_published:             # with this
            post_save_published.send(sender=self.__class__, instance=self)  #
def new_document_version_published(sender, instance, **kwargs):
    # ...


post_save_published.connect(new_document_version_published, sender=DocumentVersion)  # Add this

【讨论】:

    猜你喜欢
    • 2015-10-17
    • 2018-07-22
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多