Django中的信号就是字面意思,当发送某个信号的时候,就会触发一个或者多个函数的执行,例如,当我们每次发送短信的时候,我们可能需要将验证码保存在redis中,同时需要记录在log中,此时我们就可以实现一个信号,信号中定义了验证码的保存和log日志的记录,在每次发送短信之后,发送信号即可
使用信号在一定程度上可以帮助我们实现解耦
信号的使用流程
- 自定义一个信号
- 注册信号
- 触发信号
示例如下
# encoding:utf-8 # author:kunmzhao # email:1102669474@qq.com from django import dispatch # 1.自定义信号 my_signal = dispatch.Signal() # 2.注册信号 def save_code_to_redis(sender, **kwargs): print("保存验证码", sender, kwargs) def save_log(sender, **kwargs): print("保存日志", sender, kwargs) my_signal.connect(save_code_to_redis) my_signal.connect(save_log) # 执行信号 my_signal.send("demon")
执行结果
Django的内置信号
Model signals pre_init # django的model执行其构造方法前,自动触发 post_init # django的model执行其构造方法后,自动触发 pre_save # django的model对象保存前,自动触发 post_save # django的model对象保存后,自动触发 pre_delete # django的model对象删除前,自动触发 post_delete # django的model对象删除后,自动触发 m2m_changed # django的model中使用m2m字段操作第三张表 # (add,remove,clear)前后,自动触发 class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发 Management signals pre_migrate # 执行migrate命令前,自动触发 post_migrate # 执行migrate命令后,自动触发 Request/response signals request_started # 请求到来前,自动触发 request_finished # 请求结束后,自动触发 got_request_exception # 请求异常后,自动触发 Test signals setting_changed # 使用test测试修改配置文件时,自动触发 template_rendered # 使用test测试渲染模板时,自动触发 Database Wrappers connection_created # 创建数据库连接时,自动触发
注册信号
from django.core.signals import request_finished from django.core.signals import request_started from django.core.signals import got_request_exception from django.db.models.signals import class_prepared from django.db.models.signals import pre_init, post_init from django.db.models.signals import pre_save, post_save from django.db.models.signals import pre_delete, post_delete from django.db.models.signals import m2m_changed from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed from django.test.signals import template_rendered from django.db.backends.signals import connection_created def callback(sender, **kwargs): print("xxoo_callback") post_save.connect(callback)
触发信号
from app01 import models def demo(request): models.NewBB.objects.create(name='v1') return HttpResponse("ok")
面试题:如何在数据库中插入一条数据的时候进行Log的记录?
答案就是通过信号来实现,以下是代码详情
视图
from app01 import models from rest_framework.viewsets import ModelViewSet from rest_framework import serializers from django.db.models.signals import pre_save # 定义保存日志的代码 def perform_insert_data(sender, **kwargs): instance = kwargs["instance"] print("保存数据", sender) print("姓名:{}".format(instance.name)) print("年龄:{}".format(instance.age))
class StudentModelSerializers(serializers.ModelSerializer): class Meta: model = models.Student fields = "__all__" # Create your views here. class Student(ModelViewSet): queryset = models.Student.objects.all().order_by('-id') serializer_class = StudentModelSerializers def perform_create(self, serializer):
# 注册保存信号 pre_save.connect(perform_insert_data) serializer.save()
模型类
from django.db import models # Create your models here. class Student(models.Model): name = models.CharField(verbose_name="学生姓名", max_length=32) age = models.SmallIntegerField(verbose_name="学生年龄")
控制台输出
保存数据 <class 'app01.models.Student'> 姓名:kunmzhao 年龄:23