库尔勒网站建设价格,动漫设计和动画设计,PHP网站开发都需要学什么,ppt设计器怎么打开Django 框架包含了一个信号机制#xff0c;它允许若干个发送者#xff08;sender#xff09;通知一组接收者#xff08;receiver#xff09;某些特定操作或事件(events)已经发生了#xff0c; 接收者收到指令信号(signals)后再去执行特定的操作。本文主要讲解Django信号(…Django 框架包含了一个信号机制它允许若干个发送者sender通知一组接收者receiver某些特定操作或事件(events)已经发生了 接收者收到指令信号(signals)后再去执行特定的操作。本文主要讲解Django信号(signals)的工作机制、应用场景如何在项目中使用信号以及如何自定义信号。
信号的工作机制
Django 中的信号工作机制依赖如下三个主要要素
发送者sender信号的发出方可以是模型也可以是视图。当某个操作发生时发送者会发出信号。信号signal发送的信号本身。Django内置了许多信号比如模型保存后发出的post_save信号。接收者receiver信号的接收者其本质是一个简单的回调函数。将这个函数注册到信号上当特定的事件发生时发送者发送信号回调函数就会被执行。
信号的应用场景 信号主要用于Django项目内不同事件的联动实现程序的解耦。比如当模型A有变动时模型B与模型C收到发出的信号后同步更新。又或当一个数据表数据有所改变时监听这个信号的函数可以及时清除已失效的缓存。另外通知也是一个信号常用的场景比如有人刚刚回复了你的贴子可以通过信号进行推送。
注意Django中信号监听函数不是异步执行而是同步执行所以需要异步执行耗时的任务时(比如发送邮件或写入文件)不建议使用Django自带的信号。
Django常用内置信号
#Model signalspre_init # django的modal执行其构造方法前自动触发post_init # django的modal执行其构造方法后自动触发pre_save # django的modal对象保存前自动触发post_save # django的modal对象保存后自动触发pre_delete # django的modal对象删除前自动触发post_delete # django的modal对象删除后自动触发m2m_changed # django的modal中使用m2m字段操作第三张表add,remove,clear前后自动触发class_prepared # 程序启动时检测已注册的app中modal类对于每一个类自动触发
Management signalspre_migrate # 执行migrate命令前自动触发post_migrate # 执行migrate命令后自动触发
Request/response signalsrequest_started # 请求到来前自动触发request_finished # 请求结束后自动触发got_request_exception # 请求异常后自动触发
Test signalssetting_changed # 使用test测试修改配置文件时自动触发template_rendered # 使用test测试渲染模板时自动触发
Database Wrappersconnection_created # 创建数据库连接时自动触发 这些信号都非常有用。举个例子使用pre_save信号可以在将用户的评论存入数据库前对其进行过滤或则检测一个模型对象的字段是否发生了变更。
注意监听pre_save和post_save信号的回调函数不能再调用save()方法否则回出现死循环。另外Django的update方法不会发出pre_save和post_save的信号。 内置信号使用(当user表创建用户就给用户发个邮件)
1 写个函数 #放到__init__里 from django.db.models.signals import pre_saveimport loggingdef callBack(sender, **kwargs):logging.debug(%s创建了一个%s对象%(sender._meta.model_name,kwargs.get(instance).title))
2 绑定内置信号
pre_save.connect(callBack)
3 等待触发 pre_save #django的modal对象保存前自动触发当save()之前会触发callBack函数
还有另一种写法内置信号 from django.db.models.signals import pre_savefrom django.dispatch import receiver#监听pre_save的触发只要pre_save触发就会触发my_callback函数receiver(pre_save) def my_callback(sender, **kwargs):print(对象创建成功)print(sender)print(kwargs)
#加装饰器的这种方法其实源码内部还是将自定义函数与内置信号绑定def _decorator(func):if isinstance(signal, (list, tuple)):for s in signal:s.connect(func, **kwargs)else:signal.connect(func, **kwargs)return funcreturn _decorator 自定义信号
1 定义信号一般创建一个py文件toppingssize 是接受的参数 import django.dispatchpizza_done django.dispatch.Signal(providing_args[toppings, size])
2 注册信号
def callback(sender, **kwargs):print(callback)print(sender,kwargs)pizza_done.connect(callback)
3 触发信号 from 路径 import pizza_donepizza_done.send(senderseven,toppings123, size456) 如何正确放置Django信号的监听函数代码
当一个app的与信号相关的自定义监听函数很多时此时models.py代码将变得非常臃肿。
一个更好的方式把所以自定义的信号监听函数集中放在app对应文件夹下的signals.py文件里
便于后期集中维护。
信号的用法 1.做双写一致性的缓存更新 比如轮播图表在redis中加了缓存可以使用信号当轮播图表更新了就触发自定义的信号删除redis中的缓存。 2.我们再来看一个复杂一点的例子。我们有一个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 receiverclass Profile(models.Model):user models.OneToOneField(User, on_deletemodels.CASCADE)birth_date models.DateField(nullTrue, blankTrue)receiver(post_save, senderUser)
def create_user_profile(sender, instance, created, **kwargs):if created:Profile.objects.create(userinstance)receiver(post_save, senderUser)
def save_user_profile(sender, instance, **kwargs):instance.profile.save()