轉載出處:http://blog.csdn.net/pushiqiang/article/details/74949465 Django 信號 (Signals) 的功能類似於 WordPress 的動作 (action),用於為項目全局增加事件的廣播 (dispatch) 與接收 (receive ...
轉載出處:http://blog.csdn.net/pushiqiang/article/details/74949465
Django 信號 (Signals) 的功能類似於 WordPress 的動作 (action),用於為項目全局增加事件的廣播 (dispatch) 與接收 (receive) 機制。其中,靈活使用其內置的模型信號 (Model Signals) 的接收功能就可以監控大部分模型對象 (Model instances) 的變化。因為不需要修改模型本身的代碼,在進行跨應用 (App) 監控時有低耦合的優勢。
基本用法
信號的基本用法官方文檔上的 主題 與 參考 上已經有詳細描述。本文只提幾個要點(本文環境:Django 1.8 & Python 3.4):
代碼組織
官方推薦在應用目錄下新增一個 signals.py
文件,同時參考官方文檔的 應用配置 節中自定義應用配置 (AppConfig) ,重載應用配置類的 run
方法,在該方法內調用 from . import signals
接收信號
推薦使用 django.dispatch.receiver
這個裝飾器進行信號的接收:
from django.db.models import signals
from django.dispatch import receiver
from students.models import Student
from .models import Announcement
@receiver(signals.post_save, sender=Student)
def welcome_student(instance, created, **kwargs):
if created:
Announcement.objects.create(content='Welcome new student ' + instance.name)
從代碼可讀性的角度來講,建議一個接收函數只做一件事。
監控特定欄位 (field) 值的變化
從上一段代碼可以知道,通過接收模型 post_save
信號,可以得知發生了保存模型對象的操作,並且還可以區分出是創建了模型對象還是更新了模型對象。然而,模型信號並沒有提供針對特定欄位值變化的廣播功能,雖然該信號提供了 update_fields
參數,但是並不能證明在該參數中的欄位名的欄位值一定發生了變化,所以我們要採用一個結合 post_init
信號的變通方法。
舉一個例子:當學生名字發生改變之後發佈一條公告。
from django.db.models import signals
from django.dispatch import receiver
from students.models import Student
from .models import Announcement
@receiver(signals.post_init, sender=Student)
def welcome_student(instance, **kwargs):
instance.__original_name = instance.name
@receiver(signals.post_save, sender=Student)
def welcome_student(instance, created, **kwargs):
if not created and instance.__original_name != instance.name:
Announcement.objects.create(content=
'Student %s has renamed to %s' % (instance.__original_name, instance.name))
簡單的說就是在該模型廣播 post_init
信號的時候,在模型對象中緩存當前的欄位值;在模型廣播 post_save
(或 pre_save
)的時候,比較該模型對象的當前的欄位值與緩存的欄位值,如果不相同則認為該欄位值發生了變化。