Django中的Signal代码详解

yizhihongxing

下面我会详细讲解“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技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月16日

相关文章

  • Django用户登录与注册系统的实现示例

    下面我将详细讲解“Django用户登录与注册系统的实现示例”的完整攻略,包含两条示例说明。 第一条示例:创建Django项目并实现用户登录 1. 创建Django项目并配置数据库 首先我们需要创建一个Django项目,可以使用django-admin命令或者IDE自带的创建项目功能来创建。 然后,我们要配置数据库。在settings.py文件中,找到DATA…

    Django 2023年5月16日
    00
  • 笔记-django第一个项目

      1.      创建项目 安装 Django 之后,现在有了可用的管理工具 django-admin。可以使用 django-admin 来创建一个项目: 看下django-admin 的命令介绍:   1.1.    startproject   django-admin startproject HelloWorld   创建完成后我们可以查看下项目…

    Django 2023年4月13日
    00
  • pyinstaller打包django项目的实现步骤

    打包 Django 项目需要先使用 Pyinstaller 将 Python 代码打包成一个可执行二进制文件,然后再通过其他工具将 Django 项目打包成安装包或者 Docker 镜像。以下是详细的实现步骤: 1. 安装 Pyinstaller 在终端执行以下命令安装 Pyinstaller: pip install pyinstaller 2. 生成 D…

    Django 2023年5月16日
    00
  • Django命名空间app_name和namespace

    在多个app之间,有可能产生同名的url,这个时候避免反转url的时候混淆,可以使用应用命名空间做区分。应用命名空间使用。在应用url中定义 app_name; 一个app,可以创建多个url映射到一个app中,所以就会产生一个问题,在做反转的时候,如果不使用命名空间,就会混淆,为了避免这个问题。我们可以使用实例命名空间。在include函数中添加names…

    Django 2023年4月11日
    00
  • django自定义rbac权限组件(二级菜单)

    一、目录结构   二、表结构设计 model.py from django.db import models # Create your models here. class Menu(models.Model): “””菜单表 一级菜单””” title = models.CharField(max_length=32) icon = models.Cha…

    Django 2023年4月12日
    00
  • Python – Django – ORM 自定义 char 类型字段

    用 CharField 定义的字段在数据库中存放为 verchar 类型 自定义 char 类型字段需要下面的代码: class FixedCharField(models.Field): “”” 自定义的 char 类型的字段类 “”” def __init__(self, max_length, *args, **kwargs): self.max_le…

    Django 2023年4月10日
    00
  • 详解Django框架中用户的登录和退出的实现

    我将为你详细讲解“详解Django框架中用户的登录和退出的实现”的完整攻略。 登录和退出的实现 在Django框架中,登录和退出是非常常见的功能,因为很多应用需要用户登录来访问某些特定的内容,同时,用户退出也是必不可少的。 用户登录 实现方式 Django框架中,用户登录的实现离不开Django自带的Authentication Views组件,其中包含lo…

    Django 2023年5月16日
    00
  • Django——-Model操作

      1.字段列表 from django.bd import models AutoField(Field)   int自增列,必须有参数primary_key=True   class UserInfo(models.Model):      username=moadels.charField(max_length=32) BigAutoField(Au…

    Django 2023年4月10日
    00
合作推广
合作推广
分享本页
返回顶部