【问题标题】:Django - signals. Simple examples to startDjango - 信号。简单的例子开始
【发布时间】:2015-03-04 09:55:36
【问题描述】:

我是 Django 新手,无法理解如何使用 Django 信号。谁能用简单的例子解释一下“Django 信号”?

提前致谢。

【问题讨论】:

标签: python django django-signals


【解决方案1】:

你可以通过非常小的研究在互联网上找到关于 django 信号的非常好的内容。

在这里,我将向您简要介绍 Django 信号。
什么是 Django 信号?
信号允许某些发送者通知一组接收者某些动作已经发生

行动:

模型的 save() 方法被调用。
django.db.models.signals.pre_save | post_save

模型的 delete() 方法被调用。
django.db.models.signals.pre_delete | post_delete

模型上的 ManyToManyField 已更改。
django.db.models.signals.m2m_changed

Django 启动或完成一个 HTTP 请求。
django.core.signals.request_started |请求完成

所有信号都是 django.dispatch.Signal 实例。

非常基本的例子:

models.py

from django.db import models
from django.db.models import signals

def create_customer(sender, instance, created, **kwargs):
    print "Save is called"

class Customer(models.Model):
    name = models.CharField(max_length=16)
    description = models.CharField(max_length=32)

signals.post_save.connect(receiver=create_customer, sender=Customer)

壳牌

In [1]: obj = Customer(name='foo', description='foo in detail')

In [2]: obj.save()
Save is called

【讨论】:

  • 一个问题——为什么signals.post_save.connect(receiver=create_customer, sender=Customer)是在Customer模型的定义之后调用的?另外,为什么那行不缩进?即使没有调用类定义,那行也不会执行吗?即如果 models.py 被导入到任何地方,但实际上没有调用来自 models.py 的对象(类定义、函数等)。
  • 感觉这个答案不完整。
【解决方案2】:

除了explanation given by Prashant,你还可以使用django.dispatch模块中的receiver装饰器。

例如

from django.db import models
from django.db.models import signals
from django.dispatch import receiver

class Customer(models.Model):
    name = models.CharField(max_length=16)
    description = models.CharField(max_length=32)

@receiver(signals.pre_save, sender=Customer)
def create_customer(sender, instance, created, **kwargs):
    print "customer created"

有关详细信息,请参阅此link

【讨论】:

  • 在 Prashant 的答案中,从 signals.post_save 使用,在你的答案中从 signals.pre_save 使用,它们之间有什么区别?
  • 这两个是两个不同的信号,在 db 中的模型持久化期间在不同阶段发出。 post_save 是在保存模型之后,pre_save 是在保存模型之前。
  • post_save 用法很清楚,但pre_save 的用法是什么?
  • 这个信号是在保存模型之前触发的。你可以把它想象成一个拦截器,你可以在保存模型之前执行一些操作。
  • 这是否意味着在这种情况下 call_back 函数总是调用,除了在保存时刻?或者这意味着当您在保存 call_back 函数调用之前尝试在 Django 模型中编写文件时?
【解决方案3】:

在 signals.post_save.connect(receiver=create_customer, sender=Customer)... sender 将始终是我们定义的模型...或者我们也可以在 sender 中使用 User。

【讨论】:

    【解决方案4】:

    信号用于对模型实例的修改执行任何操作。信号是帮助我们将事件与动作联系起来的实用程序。我们可以开发一个在信号调用时运行的函数。换句话说,信号用于对数据库中特定条目的修改/创建执行一些操作。例如,一旦在数据库中创建了一个新的用户实例,就会想要创建一个配置文件实例

    有 3 种信号类型。

    1. pre_save/post_save:此信号在方法 save() 之前/之后工作。
    2. pre_delete/post_delete:此信号在删除模型实例(方法 delete())之前有效。
    3. pre_init/post_init:在实例化模型之前/之后抛出此信号(init() 方法)。

    其中一个示例,如果我们想在使用 post_save 信号创建用户后立即创建用户的个人资料。

    对于代码示例,我找到了 Geeks for Geeks,它的解释方式非常简单,易于理解。 https://www.geeksforgeeks.org/how-to-create-and-use-signals-in-django/

    【讨论】:

      【解决方案5】:

      您可以将信号添加到您的 models.py 文件中

      如果您使用 SlugField,这里是添加自动 slug 的示例:

      这是你需要导入的东西

      from django.utils.text import slugify
      from django.dispatch import receiver
      from django.db.models.signals import post_save, pre_save
      

      将@receiver 添加到类的底部,包括def

      如果在receiver下面加上def __str__(self):会报错

      class Store(models.Model):
          name = models.CharField(max_length=100)
          slug = models.SlugField(unique=False, blank=True, null=True)
      
          def __str__(self):
              return self.name
      
      @receiver(pre_save, sender=Store)
      def store_pre_save(sender, instance, *args, **kwargs):
          if not instance.slug:
              instance.slug = slugify(instance.name)
      

      或者您可以使用 post_save

      class Store(models.Model):
          name = models.CharField(max_length=100)
          slug = models.SlugField(unique=False, blank=True, null=True)
      
          def __str__(self):
              return self.name
      
      @receiver(post_save, sender=Store)
      def store_post_save(sender, instance, created, *args, **kwargs):
          if not instance.slug:
              instance.slug = slugify(instance.name)
              instance.save()
      

      我从tutorial找到了这个例子

      【讨论】:

        猜你喜欢
        • 2018-01-06
        • 1970-01-01
        • 2012-11-09
        • 2016-12-10
        • 2010-10-06
        • 2015-03-02
        • 2018-06-02
        • 1970-01-01
        • 2016-01-28
        相关资源
        最近更新 更多