Django中的Signals和GenericForeignKey的使用

Signals 顧名思義,就是信號的意思。python

Django的signals能夠用來幹什麼呢?好比,論壇中別人給你發了一條消息,自動產生一個消息對象。web

咱們先來自定義一個信號數據庫

Message應用中的models.pydjango

from django.db import models
from django.contrib.auth.models import User
from django.dispatch import Signal
notice_signal = Signal(providing_args=['reciver']) #自定義信號
class Message(models.Model):
    sender = models.ForeignKey(User)
    content = models.CharField(max_length=50)
    def newMessage(self,reciver):
        notice_signel.send(sender=self.__class__,reciver=reciver) #發出信號

Notice應用中的models.py函數

from django.db import models
from django.contrib.auth.modesl import User
from Message.models import notice_signal
class Notice(models.Model):
    reciver = models.ForeignKey(User)
    def sendNotice(sender,reciver,**kwargs):
        Notice.create(reciver=reciver)
notice_signal.connect(sendNotice,sender=Message) #接收信號

這樣,只有在建立一個Message對象後,調用newMessage函數,就會自動建立一個Notice對象,實現相似新消息通知的功能。post


更復雜的一個例子,我說我要學習,學什麼呢,學數據庫(一個model),算是學習,學一門語言(另一個model)也算是學習。我但願每學同樣東西,會自動產生一個學習事件model。這樣我在查詢我所學的知識時,只須要對學習事件進行查詢就可以方便獲取全部學過的東西的對象。學習

from django.db import models
from django.contrib.auth.modesl import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
Class StudyEvent(models.Model):
    #如下三個成員必須指定
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    #其它須要字段
    user = models.ForeignKey(User)
    start_time = models.models.DateTimeField(auto_now=True)
    #……
class StudyDatabase(models.Model):
    content = models.CharField(max_length=50)
class StudyLanguage(models.Model):
    content = models.CharField(max_length=50)

由於有時候學數據庫和學一門語言要包含一些不一樣字段,因此須要兩個models。spa


而後,讓咱們來添加Signal.net

models.pycode

#頭部添加
from django.db.models.signals import post_save #即對象在建立時會發出的信號
#尾部
def autoCreateStudyEvent(sender,**kwagrs):
    instance = kwargs.get('instance')
    if instance.__class__.__name__ == 'StudyDatabase':
        studyevent = StudyEvent.create(content_object=instance)
  &nbsp;<span></span> elif instance.__class__.__name__ == 'StudyLanguage':
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; studyevent = StudyEvent.create(content_object=instance)
post_save.connect(autoCreateStudyEvent,sender=StudyDatabase)
post_save.connect(autoCreateStudyEvent,sender=StudyLanguage)<span></span>

這樣,在建立StudyDatebase和StudyLanguage時會自動建立相應的StudyEvent對象。

如今,例若有一個用戶叫user1,獲取它全部學過的東西只須要:

import datetime
user1 = User.objects.get(username="user1")
studyevents = user1.studyevent_set.filter(start_time=datetime.datetime(2013,8,11)) #獲取在8月11日學到的知識
for studyevent in studyevents:
    print studyevent.content_object

這樣的好處在於,之後添加了新的models,在獲取全部所學過的知識時,不須要從新添加不少代碼。

http://my.oschina.net/u/572994/blog/151871
相關文章
相關標籤/搜索