阿小信大人的头像
做你说过的,说你能做的 阿小信大人

Django中使用Signals笔记2014-09-02 04:45

# -*- coding:utf-8 -*-
# reference:http://jinhao.iteye.com/blog/218346
from django.db import models
from django.contrib import admin
##test signals
#app's models.py a good place to put registration of signal handlers.
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver, Signal
from django.core.signals import request_finished, request_started
####################################
##Event
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

#A person model
class Person(models.Model):
    name = models.CharField(verbose_name=u"姓名", max_length=4)
    sex = models.CharField(verbose_name=u"性别", max_length=2, choices=((u'男', u'男'), (u'女', u'女')))
    age = models.IntegerField(verbose_name=u"年龄")

    #event
    events = generic.GenericRelation('Event')

    def __unicode__(self):
        return self.name

    #sending signals
    def send_saying_signal(self, words, mood):
        saying.send(sender=self.__class__, the_instance=self, words=words, mood=mood)#the sender should be self.__class__, self is the instance
        print '---send signal:', words, mood

admin.site.register(Person)



#########################################

class Man(Person):
    jj = models.BooleanField(default=True)
admin.site.register(Man)

class Woman(Person):
    jj = models.BooleanField(default=False)
admin.site.register(Woman)

##two ways:

def request_finish(sender, **kwargs):
    print '---request finished'
request_finished.connect(request_finish)

@receiver(request_started)
def request_start(sender, **kwargs):
    print '---request start'


##specific sender, only sender is Person

import pdb
@receiver(pre_save, sender=Person)
def pre_save_handler(sender, **kwargs):
    #pdb.set_trace()
    print '---pre save', sender, kwargs


##dispatch_uid prevents duplicate signals
@receiver(post_save, sender=Man, dispatch_uid="ashin_unique_identifier")
def post_save_handler(sender, instance, **kwargs):#second arg must be "instance"
    print "---post save", instance
    ##event
    man = instance
    event = Event(user=User.objects.get(id=1), event=man)
    event.save()

##defining signals
saying = Signal(providing_args=["words", "mood"])  #providing_args is used???

def person_say(sender, the_instance, **kwargs):
    print '---person say', sender, the_instance, kwargs
saying.connect(person_say, sender=Person) #if sender is not self.__class__, sender=Person can't call receiver



class Event(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()

    event = generic.GenericForeignKey('content_type', 'object_id')

    def __unicode__(self):
        return self.user.username+"'s event"
admin.site.register(Event)

使用Django自带的signal有两种方式:1.使用signal_obj.connect(callback),2.在callback上使用receiver装饰器

signal的处理代码一般都写在model中,要保证最想就能被调用

要想callback只在某个model触发signal的时候才调用可以在connect或者receiver中加sender参数指定具体某个module才能触发

要保证一次只触发一次signal的话在connect或者receiver中加上dispatch_uid参数,其值可以为任意字符串或者可哈希对象

要想在callback中使用更多信息可以传递一个instance关键字参数,会接收到发送来的instance

自定义信号直接实例化Signal,providing_args参数列表貌似不要也行 - -~

用实例化后的Signal调用send方法就可以发送自定义的信号,参数自定,sender=self.class必须有,信号发送后调用对应的callback处理

使用ContentType可以将一个指定的model和任意一个model关联起来形成一个事件,被关联的model需要添加一个GenericRelation,保存事件即将指定的model和被关联的model的信息保存在新的一张表中,当model被删除后对应的新表中的记录也会被删除

如果您觉得从我的分享中得到了帮助,并且希望我的博客持续发展下去,请点击支付宝捐赠,谢谢!

若非特别声明,文章均为阿小信的个人笔记,转载请注明出处。文章如有侵权内容,请联系我,我会及时删除。

#Python#   #django
分享到:
阅读[2301] 评论[0]

你可能也感兴趣的文章推荐

本文最近访客

网友54.*.*.35[火星]2018-07-23 19:12
网友66.*.*.73[美国]2018-07-23 19:11
网友46.*.*.70[Ashburn]2018-07-23 19:07
网友203.*.*.78[韩国]2018-07-23 18:59

发表评论