正确的理解和使用Django信号(Signals)

 更新时间:2021年4月15日 10:02  点击:1432

Django 提供一个了“信号分发器”机制,允许解耦的应用在框架的其它地方发生操作时会被通知到。 通俗而讲Django信号的工作原理就是当某个事件发生的时候会发出一个信号(signals), 而监听这个信号的函数(receivers)就会立即执行。Django信号的应用场景很多,尤其是用于不同模型或程序间的联动。常见例子包括创建User对象实例时创建一对一关系的UserProfile对象实例,或者每当用户下订单时触发给管理员发邮件的动作。今天小编我就分享下如何正确使用Django的信号(signals)。

Django信号的一个简单例子

假设我们有一个如下User模型,我们希望每次有User对象新创建时都打印出有新用户注册的提示信息,我们可以使用Django信号(signals)轻松实现。我们的信号发送者sender是User模型,每当User模型执行post_save动作时就会发出信号。此时我们自定义的create_user函数一旦监听到User发出的post_save信号就会执行,先通过if created判断对象是新创建的还是被更新的;如果对象是新创建的,就会打印出提示信息。

# models.py

from django.db import models

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

class User(models.Model):
    name = models.CharField(max_length=16)
    gender = models.CharField(max_length=32, blank=True)

def create_user(sender, instance, created, **kwargs):

    if created:

        print("New user created!")

post_save.connect(create_user, sender=User)

在上例中我们使用了信号(post_save)自带的connect的方法将自定义的函数与信号发出者(sender)User模型进行了连接。在实际应用中一个更常用的方式是使用@receiver装饰器实现发送者与监听函数的连接,如下所示。@receiver(post_save, sender=User)读起来的意思就是监听User模型发出的post_save信号。

from django.db import models

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

class User(models.Model):
    name = models.CharField(max_length=16)
    gender = models.CharField(max_length=32, blank=True)

@receiver(post_save, sender=User)
def create_user(sender, instance, created, **kwargs):

    if created:

        print("New user created!")

利用Django信号实现不同模型的联动更新

我们再来看一个复杂一点的例子。我们有一个Profile模型,与User模型是一对一的关系。我们希望创建User对象实例时也创建Profile对象实例,而使用post_save更新User对象时不创建新的Profile对象。这时我们就可以自定义create_user_profile和save_user_profile两个监听函数,同时监听sender(User模型)发出的post_save信号。由于post_save可同时用于模型的创建和更新,我们用if created这个判断来加以区别。

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

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    birth_date = models.DateField(null=True, blank=True)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
   if created:
       Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

Django常用内置信号

之前的例子中我们使用的都是post_save信号,即在模型调用save()方法后才发送信号。Django其它常用内置信号还包括:

  • django.db.models.signals.pre_save & post_save在模型调用 save()方法之前或之后发送。
  • django.db.models.signals.pre_init& post_init在模型调用_init_方法之前或之后发送。
  • django.db.models.signals.pre_delete & post_delete在模型调用delete()方法或查询集调用delete() 方法之前或之后发送。
  • django.db.models.signals.m2m_changed在模型多对多关系改变后发送。
  • django.core.signals.request_started & request_finished Django建立或关闭HTTP 请求时发送。

如何正确放置Django信号的监听函数代码

在之前案例中,我们将Django信号的监听函数写在了models.py文件里。当一个app的与信号相关的自定义监听函数很多时,此时models.py代码将变得非常臃肿。一个更好的方式把所以自定义的信号监听函数集中放在app对应文件夹下的signals.py文件里,便于后期集中维护。

假如我们有个account的app,包含了User和Pofile模型,我们不仅需要在account文件夹下新建signals.py,还需要修改account文件下apps.py和__init__.py,以导入创建的信号监听函数。

# account/signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User, Profile



@receiver(post_save, sender=User)

def create_user_profile(sender, instance, created, **kwargs):

  if created:

      Profile.objects.create(user=instance)



@receiver(post_save, sender=User)

def save_user_profile(sender, instance, **kwargs):

    instance.profile.save()

# account/apps.py

from django.apps import AppConfig

class AccountConfig(AppConfig):
    name = 'account'

    def ready(self):
        import account.signals

# account/__init__.py

default_app_config = 'account.apps.AccountConfig'

小结

在本文里我们总结了Django信号(signals)的工作原理,介绍了如何使用Django信号实现模型或程序的联动。最后我们还总结了Django常用内置信号以及如何正确放置自定义的信号监听函数。欢迎关注我们更多Python Web开发和Django原创文章。

以上就是正确的理解和使用Django信号(Signals)的详细内容,更多关于Django信号(Signals)的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章

  • Django def clean()函数对表单中的数据进行验证操作

    这篇文章主要介绍了Django def clean()函数对表单中的数据进行验证操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-09
  • 在Django中使用MQTT的方法

    这篇文章主要介绍了在Django中使用MQTT的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-10
  • 解决导入django_filters不成功问题No module named 'django_filter'

    这篇文章主要介绍了解决导入django_filters不成功问题No module named 'django_filter',具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-15
  • Django项目连接MongoDB的三种方法

    本文主要介绍了Django项目连接MongoDB的三种方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-27
  • 详解如何使用Docker部署Django+MySQL8开发环境

    这篇文章主要介绍了详解如何使用Docker部署Django+MySQL8开发环境,文中通过示例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-07-19
  • Django 解决由save方法引发的错误

    这篇文章主要介绍了Django 解决由save方法引发的错误,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-21
  • django前端页面下拉选择框默认值设置方式

    这篇文章主要介绍了django前端页面下拉选择框默认值设置方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-10
  • django数据模型中null和blank的区别说明

    这篇文章主要介绍了django数据模型中null和blank的区别说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-03
  • Django表单外键选项初始化的问题及解决方法

    这篇文章主要介绍了Django表单外键选项初始化的问题及解决方法,需本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,要的朋友可以参考下...2021-04-29
  • 使用AJAX和Django获取数据的方法实例

    这篇文章主要给大家介绍了关于使用AJAX和Django获取数据的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-25
  • django ajax发送post请求的两种方法

    这篇文章主要介绍了django ajax发送post请求的两种方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-04-30
  • 浅谈Qt信号与槽的各种连接方式

    信号和槽是Qt特有的信息传输机制,本文主要介绍了浅谈Qt信号与槽的各种连接方式,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-02
  • 用c语言实现HUP信号重启进程的方法

    本篇文章是对使用c语言实现HUP信号重启进程的方法进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • 详细分析C++ 信号处理

    这篇文章主要介绍了C++ 信号处理的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-10
  • Django开发RESTful API实现增删改查(入门级)

    这篇文章主要介绍了Django开发RESTful API实现增删改查(入门级),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-10
  • Perl脚本实现检测主机心跳信号功能

    这篇文章主要介绍了Perl脚本实现检测主机心跳信号功能,本文代码也可作为perl串口通信的实例,需要的朋友可以参考下...2020-06-29
  • Django获取model中的字段名和字段的verbose_name方式

    这篇文章主要介绍了Django获取model中的字段名和字段的verbose_name方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-20
  • django中url映射规则和服务端响应顺序的实现

    这篇文章主要介绍了django中url映射规则和服务端响应顺序的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-05-10
  • Django项目如何获得SSL证书与配置HTTPS

    本文总结了如何获得SSL证书并给Django项目配置HTTPS,建议先收藏再阅读,将来有一天你很可能会用到它。...2021-05-01
  • Django后台管理系统的图文使用教学

    在本篇文章里小编给大家整理的是一篇关于Django后台管理系统的图文使用教学内容,需要的朋友们参考下。...2020-04-22