下面我会详细讲解“Django中的Signal代码详解”的完整攻略,包括两条示例说明。
什么是Signals
Signal是Django框架中一种提供了统一解耦机制的工具。Signal机制可以在软件设计中完成消息的发布和订阅功能。简单来说,Signal是一种django中内部|跨应用程序的非阻塞通信方式。
优点是:
1. 内部处理自由方便,不受调用方影响;
2. 降低代码的耦合度,提高代码的可读性;
3. 方便人性化的日志配置;
Signal的使用
安装django
若已安装,可省略此步骤。
pip install django
创建一个django项目并生成一个应用程序
django-admin startproject project
cd project
python manage.py startapp testapp # testapp为应用程序名
使用Signal完成应用程序之间的通信
Django中的Signal模块主要由以下几部分组成:
- 可在你的应用程序中本地声明的信号。
- 当接收到信号时将被调用的监听器
发送Signals
Signals在Django中使用django.dispatch.Signal
来创建。下面我们首先创建一个signal:
我们对于信号有两种方式来定义一个信号,一种就是使用Signal类,另一种就是使用signal装饰器。
我们先看看使用Signal类的方式:
# testapp.signals module
from django.dispatch import Signal
test_signal = Signal(providing_args=['arg1', 'arg2'])
监听Signals
下一步我们需要监听这个signal,并且在收到这个信号时做出反应。在Django中监听者可以是一个函数,当信号被发出时,此函数会被调用。
如下所示,我们定义一个函数,当信号被发出时就会调用此函数:
# testapp.signals listener
def handler(sender, **kwargs):
print(sender)
print(kwargs)
test_signal.connect(handler)
handler
函数定义了两个参数:sender
和**kwargs
。其中sender
实际指信号所发送的当前模版类,**kwargs
为提供给监听器的参数。
函数connect
可以将信号和监听函数绑定在一起。当事件发送时,我们先来看看会输出什么。
Test Signal
现在看完了简答的信号和监听器,接下来让我们看看它们在Django项目中是如何协作的。
我们在某个地方发送signal:
# testapp.function sender
from .signals import test_signal
test_signal.send(sender=self.__class__, arg1='arg1', arg2='arg2')
Send方法:它用于将信号发送给一个或多个接收器,作为一个“写入入口”,使用Signal.connect()方法将多个接收器绑定到同一个信号上,该方法将逐一触发该信号。
最后,让我们来创建一个Django的示例程序,演示信号和监听器是如何协同工作的。
一个Django的示例程序
创建一个名为Signaltute的Django项目和一个名为Testapp的应用程序:
django-admin startproject signaltute
cd signaltute
python manage.py startapp testapp
现在我们来为我们的应用创建一些新的文件:
# signals.py
from django.dispatch import Signal
test_signal = Signal() # 创建信号
# listeners.py
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from testapp.signals import test_signal
User = get_user_model()
# 发送者 要获得当前发送信息的model
# **kwargs 从信号发送者获得的实际值
@receiver(test_signal)
def test_signal_handler(sender, **kwargs):
print("aaa")
@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
print("test")
# models.py
# -*- coding: utf-8 -*-
from django.db import models
class BaseModel(models.Model):
class Meta:
abstract = True
class Test(BaseModel):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
运行python manage.py makemigrations && python manage.py migrate
, Django便可创建相应的表。
最后,在应用的views.py
中添加以下代码:
import random
from django.contrib.auth import get_user_model
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import TemplateView
from testapp.listeners import test_signal_handler
from testapp.models import Test
from testapp.signals import test_signal
User = get_user_model()
class HomePageView(TemplateView):
template_name = 'home.html'
def test_signal_view(request):
test_signal.connect(test_signal_handler) # 绑定信号和监听器
test_instance = Test(name=f'test_instance_{random.randint(1, 100)}')
test_instance.save()
test_signal.send(sender=request.user)
return HttpResponse('OK')
请注意,我们在test_signal_view中连接了test_signal并指定test_signal_handler为它的接收者。
运行Django开发服务器并通过URL http://127.0.0.1:8000/test_signal/ 调用test_signal_view视图。
test_signal_handler
是最终的监听器,我们期望代码输出”aaa”
示例二
signals.py:
from django.dispatch import Signal
# 创建一个信号hr_read
hr_read = Signal(providing_args=["request", "workflow", "todo", "data"])
使用Signal类是最基本、最灵活的方式。这允许我们在运行时添加或删除接收器,并允许我们在不使用“post_ **”信号的情况下发出自己的信号。
以下是单个监听器的示例:
from django.dispatch import receiver
from .signals import hr_read
@receiver(hr_read)
def read_the_mail(sender, **kwargs):
print(sender)
print(kwargs)
在接收到信号hr_read时,将打印sender和kwargs。
Q&A
-
区别Signal和其他消息传递机制(例如在Python中的类events.Event)
Signals是帮助我们将我们的代码解耦的工具,因为它们实现了事件驱动的交互模型。Signals允许我们将事件从方法或逻辑中分离出来,最大程度地减少代码的聚合组件。与其他事件通知模型不同的是,Signals不是一种阻塞消息传递模型,而是一种灵活、松散的事件传递模型,这是一种十分基于异步通信的解决方案。 -
如何在应用中使用多个监听器?
Signal可以被多个接收器绑定,我们把一个信号绑定到两个接收器,它会将信号传递给两个接收器。但是,我们需要保证这两个接收器不相互干扰。 -
admin功能,自动化邮件如何使用Signal来实现?
django.contrib.auth.signals.user_logged_in
在登录后每次活动中触发,允许其他应用程序扩展来封锁或界定特定时期的管理操作。邮箱提醒可以帮助管理员监控此优先级外部事件。
以上就是Django中的Signal的详细攻略,希望对你有所帮助!
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django中的Signal代码详解 - Python技术站