0

django拾遗之signal

 2 years ago
source link: https://www.cnblogs.com/mindsbook/archive/2009/10/27/django_signal.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

如何使用django的signal

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

参考下图:

http://farm3.static.flickr.com/2468/4048888885_23bf82c838_o.png

那么我们来逐步完成我们简单的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 == "POST":
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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK