1. 程式人生 > >[TimLinux] Django 信號

[TimLinux] Django 信號

一個 現在 情況 and 有一個 之前 3.3 信號 receive

1. 信號定義

django包含有一個“信號分發器”,在框架內任何時候,在任何地方,有動作方式是,用來幫助解耦應用之間獲取通知。簡言之,信號允許特定的發送者通知一系列接收者動作已經發生了。特別有用的地方在於:許多代碼片段對於同樣的事件感興趣。

2. 內建信號

django提供了許多內建的信號,這樣用戶代碼能夠在django自身的一些特定動作發生時得到通知。如下:

  • django.db.models.singals.pre_save、django.db.models.signals.post_save:在模型的save()方法被調用之前、之後發送該信號。
  • django.db.models.signals.pre_delete、django.db.models.signals.post_delete:在模型的delete()方法被調用之前、之後發送該信號。
  • django.db.models.signals.m2m_chagned:當一個ManyToManyField模型發送修改是發送該信號。
  • django.core.signals.request_started、django.core.signals.request_finished:在django開始、完成一個HTTP請求時發送該信息。
  • 等等其他信號。

3. 監聽信號

為了接收一個信號,使用Signal.connect()方法來註冊一個信號接收函數,當信號被發送的時候接收函數將被調用。函數接口如下:

Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)

參數說明:
receiver: 回調函數,將被連接到對象的信號上。receiver函數有它的實現要求
sender: 指定一個特定的發送者,明確信號從哪裏來的。
weak: django存儲信號處理器默認作為弱引用。可以通過設置weak
=False來修改這一行為。 dispatch_uid: 信號接收者的唯一標識,以免重復信號被發送。

例如:request_finished就是一個Signal對象,下面這行代碼完成了信號的監聽
request_finished.connect(my_callback)

下面的函數定義,完成了接收函數的定義
def my_callback(sender, **kwargs):
print("Request finished!")

3.1. 接收函數

接收函數可以是任意Python函數或方法:接收一個sender位置參數,一個通配的kwargs關鍵字參數,所有信號處理器必須接收這些參數。所有的信號發生kwargs參數,並且可能在任一時間改變這些關鍵字參數。根據request_finished信號文檔說明,它不會發送任何參數,看似上面的回調函數也可能不傳遞關鍵字參數,但是這樣的操作是錯誤的,如果你真的這樣做,django會拋出一個錯誤的。

3.2. 連接接收函數

兩種方式可以將一個接收者連接到信號上去。

# 1. 手動連接
from django.core.signals import request_finished

def my_callback(sender, **kwargs):
    print("Request finished!")
request_finished.connect(my_callback)


# 2. 使用 receiver 裝飾器連接
from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")

現在my_callback函數會在每次完成完成一次請求之後被調用。

3.3. 連接信號:指定發送者

指定發送者的目的是縮小事件的監聽範圍,比如pre_save()信號,多數情況下只是想知道某一個特定的模型上發生的這一信號,而不是所有的模型。這時候就可以指定你所關心的sender,比如sender=User,那麽只有當User模型在pre_save信號發送時,才調用receiver函數。不同的信號,能夠接收的sender參數是值不同,需要根據信號文檔描述進行設置,不能亂猜哦!

from django.core.signals import pre_save
from django.dispatch import receiver
from myapp.models import User

@receiver(pre_save, sender=User)
def my_handler(sender, **kwargs):
    print("pre_save happen in User.")

3.4. 阻止重復信號

[TimLinux] Django 信號