`
xiaolin0199
  • 浏览: 573396 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

[转]django拾遗之signal

阅读更多

在web开发中, 你可能会遇到下面这种场景:


在用户完成某个操作后, 自动去执行一些后续的操作. 譬如用户完成修改密码后,你要发送一份确认邮件.当然你可以把逻辑写在一起, 但是有个问题是, 通常前置动作(触发操作)会不止一种(如用户更改了其它信息的确认邮件), 这时候这个逻辑会需要写多次, 所以你可能会想着DRY, 于是你把它写到了一个函数中,每次调用. 当然这是没问题的.
但是, 如果你换个思路你会发现另一个完全不同的方案, 即:
1.类似于daemon的程序监听着特定的事件
2.前置操作来触发相应的事件
3.监听程序执行对应的操作
这样的好处是什么呢?
1.松耦合(不用把后续操作写在主逻辑中)
2.便于复用(这也是为什么 django 本身, 及第三方应用如 pinax 大量使用此技术的原因)
在各种高级语言中都会有类似的特性,如java, javascript等.而在 django 中我们使用 signal.


本文会着重介绍 django 的 signal 相关知识.
django的signal定义什么是signal?
django 包含一个称为 signal dispatcher, 用来解耦合框架中发生的事件与 得到通知的应用 之间的逻辑. 简单地说, 在特定事件发生时, 使用signal 发送者 能够通知一系列 接收者(一个或者多个).
python 本身没有类似机制的支持, 但是 django 基于 PyDispatcher 进行了性能 和代码结构上的优化来增加了signal功能.


如何使用django的signal在使用signal之前,我们先了解下django signal的处理流程.

 那么我们来逐步完成我们简单的signal.

场景我们有2个页面 ,一个是文章显示页面,一个是文章增加页面, 文章只有title,content及is_public三个域.
我们使用signal是完成,当用户添加一个文章后,我们置其is_public=False, 我们使用signal来实现此功能.


注册signal下面是测试用的project的文件结构,具体可以 下载源代码 来在本地运行.

|-- __init__.py
|-- __init__.pyc
|-- logs
|   `-- filelog.log
|-- manage.py
|-- settings.py
|-- settings.pyc
|-- signal.db
|-- testsignal
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- models.py
|   |-- models.pyc
|   |-- signals.py
|   |-- signals.pyc
|   |-- templates
|   |   |-- add.html
|   |   |-- base.html
|   |   `-- index.html
|   |-- tests.py
|   |-- urls.py
|   |-- urls.pyc
|   |-- views.py
|   `-- views.pyc
|-- urls.py
`-- urls.pyc

  testsignal是我们建立的示例app, 我们首先要注册signal, 具体代码如下(testsignal/signals.py):

import django.dispatch
delete_done = django.dispatch.Signal(providing_args=['obj'])

  引入django的包, 并且注册 delete_done为我们将要使用的signal.

  关联signal对应的listener然后我们关联对应的listener, 代码如下: (testsignal/models.py)

 

 

from django.db.models.signals import pre_save
from django.db import models
import logging
import signals
# Create your models here.

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_public = models.BooleanField(default=True, blank=True)
    def delete(self):
        #self.is_public = False
        signals.delete_done.send(sender=Article, obj=self)
    def __unicode__(self):
        return self.title

def zhutao(sender, kwargs):
    logging.debug(kwargs)
    if "obj" in kwargs:
        obj = kwargs.get("obj")
        logging.debug(obj.is_public)
        obj.is_public = False
        obj.save()
        logging.debug("signal recieved! zhutao is called.")
        logging.debug(obj.is_public)
signals.delete_done.connect(zhutao, sender=Article)

  我们来看最后一行, signals.delete_done.connect(zhutao, sender=Article), 即将 我们上面注册的 delete_done 和 监听函数 zhutao 关联了起来, 而 这里的 sender=Article, 则是用来限制只有当Article有更新时我们才会触发这个事件.

触发监听事件最后,我们要在特定操作发生时触发相应的监听函数, 具体代码如下(testsignal/views.py):

from django.http import HttpResponse,HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
import signals
from models import *

def index(request):
   articles = Article.objects.all().order_by("-id")
   return render_to_response("index.html", {"articles":articles})
def add(request):
    if request.method == "OST":
        title = request.POST.get("title", "")
        content = request.POST.get("content", "")
        if title and content:
            article = Article(title=title, content=content)
            article.save()
            article.delete()
            return HttpResponseRedirect(reverse(index))
    return render_to_response("add.html", {})

  其它的只是django的普通views.py中的方法,我们主要来看 article.delete() 这行代码, 执行这个后,我们会调用models.py中的delete方法,见上面的models.py中的代码, 它会执行下面一行代码:
signals.delete_done.send(sender=Article, obj=self)

面这行代码正是向delete_done发送了事件的触发,此时,对应的监听函数 zhutao 会得到执行,
从而将 is_public 置为False.
我们的任务也得以完成.
具体的说明可以 下载源代码 来运行,你会在logs/filelog.log文件中看到对应的log输出.
示例输出为:

2009-10-27 03:28:27,202 DEBUG models.zhutao Line:26 {'signal': <django.dispatch.dispatcher.Signal object at 0x9523e4c>, 'obj': <Article: aaa>}
2009-10-27 03:28:27,203 DEBUG models.zhutao Line:29 True
2009-10-27 03:28:27,209 DEBUG models.zhutao Line:32 signal recieved! zhutao is called.
2009-10-27 03:28:27,209 DEBUG models.zhutao Line:33 False
  一些其它的应用我们上面提到过 django, pinax 也大量地使用了signal技术,那我们下面简要看看, django 中有哪些具体的应用.
在 django 中, 主要有下面几类:
1.Model signals
        1.pre_init
        2.post_init
        3.pre_save
        4.post_save
        5.pre_delete
        6.post_delete
        7.class_prepared
2.Management signals
        1.post_syncdb
3.Request/response signals
        1.request_started
        2.request_finished
        3.got_request_exception
4.Test signals
        1.template_rendered
这些都是 django 内置的signals来方便用户来进行一些特定的操作,具体的介绍可以参考: built-in signals.
至于 pinax 可以下载其源代码来具体查看.


可能的应用场景那么signals有哪些可能的应用场景呢?我们能够在什么样的场景下使用呢?
从定义来看,其实已经很明确了, 如果一个操作可能会触发多个后续事件, 此时使用signals会非常方便.
那么具体的应用可以考虑:
sns中的事件通知, 如用户发表了一篇博文, 然后通知所有的好友
用户信息的更改的邮件通知
用户订制信息的邮件通知等

结论django 的signals是非常强大的, 如果我们能够很好地使用,则能够大大地提高代码的可维护性, 复用性,以及减少耦合等.
分享到:
评论
1 楼 edison0951 2010-04-24  
这篇文章有深度,不错。

相关推荐

    Django中自带的Signal的使用

    在Django框架中,Signal是一种强大的机制,它允许开发者在特定事件发生时执行代码,而无需显式调用。Signal的使用可以极大地提高代码的可维护性和灵活性,尤其是在大型项目中,它能帮助我们实现各个组件之间的解耦。...

    Python Django建站教程源代码《玩转Django2.0》配套全部源码 共13个章节 含目录内容.rar

    第1章 Django建站基础 1 1.1 网站的定义及组成 1 1.2 网站的分类 3 1.3 网站运行原理及开发流程 5 1.4 走进Django 6 1.5 Django 2.0的新特性 7 1.6 安装Django 8 1.7 创建项目 9 1.8 PyCharm搭建开发环境 12 1.9 本...

    Django客户管理系统源码.zip

    Django客户管理系统源码 Django客户管理系统源码 Django客户管理系统源码 Django客户管理系统源码 Django客户管理系统源码 Django客户管理系统源码 Django客户管理系统源码 Django客户管理系统...

    Django By Examples按章节源代码(Django2.0版本)

    【Django by Examples按章节源代码(Django2.0版本)】 Django是一个用Python编写的高级Web框架,它鼓励快速开发并遵循“DRY”(Don't Repeat Yourself)原则。Django 2.0是该框架的一个重要版本,引入了多项改进和...

    玩转django2.0同款音乐网站使用django编写.zip

    玩转django2.0同款音乐网站使用django编写.zip

    Django框架之登录后自定义跳转页面的实现方法

    Django auth 登陆后页面跳转至/account/profile,修改跳转至其他页面 这几天在学习django,django功能很强大,自带的auth,基本可以满足用户注册登陆登出,简单的用户注册登陆系统使用django auth足矣。当然也不是拿...

    django电子商务网站源码.zip

    django电子商务网站源码 django电子商务网站源码 django电子商务网站源码 django电子商务网站源码 django电子商务网站源码 django电子商务网站源码 django电子商务网站源码 django电子商务网站源码 django...

    Django实现商城网站源码.zip

    Django实现商城网站源码 Django实现商城网站源码 Django实现商城网站源码 Django实现商城网站源码 Django实现商城网站源码 Django实现商城网站源码 Django实现商城网站源码 Django实现商城网站源码 Django...

    基于Django的个人网盘源码.zip

    基于Django的个人网盘源码 基于Django的个人网盘源码 基于Django的个人网盘源码 基于Django的个人网盘源码 基于Django的个人网盘源码 基于Django的个人网盘源码 基于Django的个人网盘源码 基于Django...

    django笔记 django笔记

    Django是Python编程语言中的一款强大且流行的Web框架,它以“快速开发”和“约定优于配置”的理念为核心,让开发者能够高效地构建高质量的Web应用程序。本笔记将深入探讨Django的基础概念、核心功能以及实际应用。 ...

    Python基于Django的就业系统源码.zip

    基于Django就业系统源码 基于Django就业系统源码 基于Django就业系统源码 基于Django就业系统源码 基于Django就业系统源码 基于Django就业系统源码 基于Django就业系统源码 基于Django就业系统源码 基于...

    django项目实例(django 简易博客开发)

    前几天写的django 简易博客开发记录,贴个链接吧 django 简易博客开发 1 安装、创建、配置、admin使用 http://www.cnblogs.com/cacique/archive/2012/09/29/2707976.html django 简易博客开发 2 模板和数据查询 ...

    django4中文文档

    django4最新中文文档+适合python初学或者初次接触django4的开发者 从事Python编程工作的人员,一定听说过这三个框架:Django、Flask、Tornado,它们就像神一样的存在 Django是最有代表性的一种。许多成功的网站和APP...

    Django实现在线视频课堂播放网站源码.zip

    Django实现在线视频课堂播放网站源码 Django实现在线视频课堂播放网站源码 Django实现在线视频课堂播放网站源码 Django实现在线视频课堂播放网站源码 Django实现在线视频课堂播放网站源码 Django实现在线视频...

    PYTHON之Django Web框架源码下载

    使用 Django,我们在几分钟之内就可以创建高品质、易维护、数据库驱动的应用程序。 Django框架的核心组件有: 1、用于创建模型的对象关系映射 2、为最终用户设计的完美管理界面 3、一流的URL设计 4、设计者友好的...

    Django从零开发的个人博客网站源码.zip

    Django从零开发的个人博客网站源码 Django从零开发的个人博客网站源码 Django从零开发的个人博客网站源码 Django从零开发的个人博客网站源码 Django从零开发的个人博客网站源码 Django从零开发的个人博客...

    django+scrapy结合

    本篇文章将详细探讨如何将两个强大的Python库——Django和Scrapy结合,以实现通过Django的Web界面控制Scrapy爬虫的运行,并将爬取的数据存入数据库。 首先,让我们了解这两个框架的基本概念。Django是一个高级的Web...

    django4.0官方中文文档

    2. **模型(Models)**:Django的核心之一就是ORM(对象关系映射),它允许开发者用Python类来定义数据库表结构。在模型文件中,我们可以定义字段、属性以及字段间的关系,如外键、一对多和多对多等。 3. **视图...

Global site tag (gtag.js) - Google Analytics