Django中的信號

信號

Django 提供一個「信號分發器」,容許解耦的應用在框架的其它地方發生操做時會被通知到。 簡單來講,信號容許特定的sender通知一組receiver某些操做已經發生。 這在多處代碼和同一事件有關聯的狀況下頗有用。mysql

內置信號

模型信號

django.db.models.signals模塊定義了模型系統發送的一組信號。面試

pre_init

django.db.models.signals.pre_init
每當您實例化Django模型時,該信號都會在模型的__init__()方法的開頭髮送。sql

帶有此信號的參數:數據庫

sender
剛建立了一個實例的模型類。
ARGS
傳遞給__init__()的位置參數列表:
kwargs
傳遞給__init__()的關鍵字參數的字典:django

例如:後端

from app01 import models

p = models.Publisher(name='沙河出版社')

發送到pre_init處理程序的參數將是:安全

 

參數
sender Publisher(類自己)
ARGS [](一個空列表,由於沒有位置參數傳遞給__init__()。)
kwargs {'name': 「沙河出版社}

 

pre_save

django.db.models.signals.pre_save
這是在模型的save()方法的開頭髮送的。服務器

帶有此信號的參數:app

sender
模型類。
instance
正在保存的實際實例。
raw
一個布爾值True若是模型按照顯示的方式保存(即當加載固定裝置時)。 不該該查詢/修改數據庫中的其餘記錄,由於數據庫可能還沒有處於一致狀態。
using
正在使用的數據庫別名。
update_fields
若是有字段被傳遞給Model.save()方法那麼就是所傳遞的字段集,不然就是None。框架

post_save

django.db.models.signals.post_save
像pre_save同樣,可是在save()方法的末尾發送。

帶有此信號的參數:

sender
模型類。
instance
正在保存的實際實例。
created
一個布爾值True若是建立了新記錄。
raw
一個布爾值True若是模型按照顯示的方式保存(即當加載固定裝置時)。 不該該查詢/修改數據庫中的其餘記錄,由於數據庫可能還沒有處於一致狀態。
using
正在使用的數據庫別名。
update_fields
若是有字段被傳遞給Model.save()方法那麼就是所傳遞的字段集,不然就是None。

pre_delete

django.db.models.signals.pre_delete
在模型的delete()方法和queryset的delete()方法的開頭髮送。

帶有此信號的參數:

sender
模型類。
instance
正在刪除的實際實例。
using
正在使用的數據庫別名。

post_delete

django.db.models.signals.post_delete
像pre_delete同樣,可是在模型的delete()方法和queryset的delete()方法的末尾發送。

帶有此信號的參數:

sender
模型類。
instance
正在刪除的實際實例。

請注意,該對象將再也不位於數據庫中,因此要很是當心使用此實例。

using
正在使用的數據庫別名。

m2m_changed

django.db.models.signals.m2m_changed
在模型實例上更改了ManyToManyField時發送。 嚴格來講,這不是一個模型信號,由於它是由ManyToManyField發送的,但因爲它補充了pre_save / post_save和pre_delete / post_delete當跟蹤模型的更改時,它包括在這裏。

帶有此信號的參數:

sender
描述ManyToManyField的中間模型類。 當定義多對多字段時,此類自動建立;您可使用多對多字段上的through屬性訪問它。
instance
多對多關係更新的實例。 這能夠是sender或ManyToManyField相關的類的一個實例。
action
指示在關係上完成的更新類型的字符串。 這能夠是如下之一:

「pre_add」
在以前發送一個或多個對象被添加到關係中。
「post_add」
在以後發送一個或多個對象被添加到關係中。
「pre_remove」
在以前發送一個或多個對象從關係中刪除。
「post_remove」
在以後發送一個或多個對象從關係中刪除。
「pre_clear」
在以前發送關係被清除。
「post_clear」
以後發送關係被清除。
reverse
指示關係的哪一側被更新(即,若是它是正在被修改的正向或反向關係)。
model
添加到,從關係中刪除或從關係中清除的對象的類。
pk_set
對於pre_add,post_add,pre_remove和post_remove操做,這是一組主鍵值加入或從關係中刪除。

對於pre_clear和post_clear操做,這是None。

using
正在使用的數據庫別名。

class_prepared

django.db.models.signals.class_prepared
每當模型類「準備」時發送 - 即,一旦模型已經被定義並在Django的模型系統中註冊。 Django內部使用這個信號;它一般不會用於第三方應用程序。

因爲此信號是在應用程序註冊表羣集進程期間發送的,而且在應用註冊表徹底填充後運行AppConfig.ready(),所以沒法使用該方法鏈接接收器。 一種可能性是鏈接他們AppConfig.__init__(),注意不要導入模型或觸發對應用程序註冊表的調用。

使用此信號發送的參數:

sender
ready的model類。

管理信號

pre_migrate

django.db.models.signals.pre_migrate
在開始安裝應用程序以前,由migrate命令發送。 對於缺乏models模塊的應用,不會發送。

帶有此信號的參數:

sender
應用程序即將遷移/同步的AppConfig實例。
APP_CONFIG
與sender相同。
verbosity
指示manage.py在屏幕上打印多少信息。 有關詳細信息,請參閱--verbosity標誌。

監聽pre_migrate的函數應根據該參數的值調整輸出到屏幕的內容。

interactive
若是interactive是True,則能夠安全地提示用戶在命令行中輸入內容。 若是interactive爲False,則偵聽此信號的功能不該嘗試提示任何內容。

例如,當interactive爲True時,django.contrib.auth應用程序僅提示建立超級用戶。

using
命令將在其上運行的數據庫的別名。
plan
Django中的新功能1.10。
遷移計劃將用於遷移運行。 雖然該計劃不是公共API,但這在容許罕見的狀況下須要知道計劃。 一個計劃是兩個元組的列表,第一個項目是遷移類的實例,第二個項目顯示遷移是否回滾(True)或應用(False

apps
Django中的新功能1.10。
包含遷移運行前的項目狀態的Apps的實例。 應該使用它來代替全局apps註冊表來檢索要執行操做的模型。

post_migrate

django.db.models.signals.post_migrate
在migrate(即便不進行遷移)和flush命令的末尾發送。 對於缺乏models模塊的應用,不會發送。

此信號的處理程序不得執行數據庫模式更改,由於若是在migrate命令期間運行,則可能會致使flush命令失敗。

帶有此信號的參數:

sender
剛剛安裝的應用程序的AppConfig實例。
APP_CONFIG
與sender相同。
verbosity
指示manage.py在屏幕上打印多少信息。 有關詳細信息,請參閱--verbosity標誌。

監聽post_migrate的函數應根據此參數的值調整輸出到屏幕的內容。

interactive
若是interactive是True,則能夠安全地提示用戶在命令行中輸入內容。 若是interactive爲False,則偵聽此信號的功能不該嘗試提示任何內容。

例如,當interactive爲True時,django.contrib.auth應用程序僅提示建立超級用戶。

using
用於同步的數據庫別名。 默認爲default數據庫。
plan
Django中的新功能1.10。
用於遷移運行的遷移計劃。 雖然該計劃不是公共API,但這在容許罕見的狀況下須要知道計劃。 一個計劃是兩個元組的列表,第一個項目是遷移類的實例,第二個項目顯示遷移是否回滾(True)或應用(False

apps
Django中的新功能1.10。
包含遷移運行後項目狀態的Apps的實例。 應該使用它來代替全局apps註冊表來檢索要執行操做的模型。

請求/響應信號

處理請求時由核心框架發送的信號。

request_started

django.core.signals. request_started
當Django開始處理HTTP請求時發送。

帶有此信號的參數:

sender
處理程序類 - 例如django.core.handlers.wsgi.WsgiHandler - 處理該請求。
ENVIRON
environ字典提供給請求。

request_finished

django.core.signals.request_finished
當Django完成向客戶端傳遞HTTP響應時發送。

帶有此信號的參數:

sender
處理程序類,如上。

got_request_exception

django.core.signals. got_request_exception
當Django在處理傳入的HTTP請求時遇到異常時,會發送此信號。

帶有此信號的參數:

sender
處理程序類,如上。
request
HttpRequest對象。

測試信號

信號只在running tests時發送。

setting_changed

django.test.signals.setting_changed
當經過django.test.TestCase.settings()上下文管理器或django.test.override_settings()裝飾器/上下文管理器

實際發送兩次:應用新值(「setup」)和恢復原始值(「拆除」)時。 使用enter參數來區分二者。

您還能夠從django.core.signals導入此信號,以免在非測試狀況下從django.test導入。

帶有此信號的參數:

sender
設置處理程序。
setting
設置的名稱。
value
更改後的設置值。 對於最初不存在的設置,在「拆卸」階段,value爲None。
enter
一個布爾值True若是應用設置,False若是還原。

template_rendered

django.test.signals.template_rendered
測試系統呈現模板時發送。 在Django服務器的正常操做期間不發出此信號 - 它僅在測試期間可用。

帶有此信號的參數:

sender
被渲染的Template對象。
template
與發信人相同
context
模板呈現的Context。

數據庫包裝器

當數據庫鏈接啓動時,由數據庫包裝器發送的信號。

connection_created

django.db.backends.signals.connection_created
當數據庫包裝器與數據庫進行初始鏈接時發送。 若是您想將任何後續鏈接命令發送到SQL後端,這一點尤爲有用。

帶有此信號的參數:

sender
數據庫包裝器類 - 即django.db.backends.postgresql.DatabaseWrapper或django.db.backends.mysql.DatabaseWrapper等
connection
打開的數據庫鏈接。 這能夠在多數據庫配置中使用,以區分來自不一樣數據庫的鏈接信號。

使用信號

回到前面的面試圖,如何在Django中實現每一次ORM保存到數據庫的時候執行指定操做?

Receiver函數

Receiver能夠是任何Python函數或者方法:

def my_callback(sender, **kwargs):
    print(sender)
    print(kwargs)
    print("要保存了啊!")
    print('-' * 120)

監聽信號

一旦某個指定信號觸發,就執行我指定的receiver函數。

咱們如今的需求是,模型層一執行保存的動做就作什麼事。

因此應該是一旦觸發 pre_save 信號就執行 my_callback,對於內置的信號Django框架會自動幫咱們觸發,咱們只須要告訴它信號觸發以後作什麼事就能夠了:

pre_save.connect(my_callback)

接下來,只要涉及到ORMC鞥面的save()操做,都會自動執行我定義的my_callback函數了。

例如:

a3 = Author.objects.create(name='測試信號-做者')
b3 = Book.objects.create(title='測試信號-書')

輸出:

<class 'app02.models.Author'>
{'signal': <django.db.models.signals.ModelSignal object at 0x108e0d198>, 'instance': <Author: 測試信號-做者>, 'raw': False, 'using': 'default', 'update_fields': None}
要保存了啊!
------------------------------------------------------------------------------------------------------------------------
(0.001) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.001) INSERT INTO `app02_author` (`name`) VALUES ('測試信號-做者'); args=['測試信號-做者']
<class 'app02.models.Book'>
{'signal': <django.db.models.signals.ModelSignal object at 0x108e0d198>, 'instance': <Book: 測試信號-書>, 'raw': False, 'using': 'default', 'update_fields': None}
要保存了啊!
------------------------------------------------------------------------------------------------------------------------
(0.001) INSERT INTO `app02_book` (`title`) VALUES ('測試信號-書'); args=['測試信號-書']

使用裝飾器方式監聽信號

# 使用裝飾器方式
from django.db.models.signals import pre_save
from django.dispatch import receiver


@receiver(pre_save)
def my_callback(sender, **kwargs):
    print(sender)
    print(kwargs)
    print("要保存了啊!")
    print('-' * 120)

自定義信號

上面列出來的都是Django框架內置的信號,固然咱們還能夠自定義信號。

定義信號

全部信號都是 django.dispatch.Signal 的實例。 providing_args是一個列表,由信號將提供給監聽者的參數名稱組成。 理論上是這樣,可是實際上並無任何檢查來保證向監聽者提供了這些參數。

舉個例子:

# 自定義信號
from django.dispatch import Signal

bath_done = Signal(providing_args=['amount', 'temperature'])

這裏定義了一個洗澡水燒好了的信號,它接受兩個參數:amount表示水量,temperature表示溫度。

註冊receiver

from django.dispatch import receiver

@receiver(bath_done)
def my_action(sender, **kwargs):
    print(sender)
    print(kwargs)
    print('脫衣服泡個澡吧!')

觸發信號

斯嘉麗燒好了一浴缸40度的洗澡水,杜蘭特要開喝了。

bath_done.send(sender='斯嘉麗', amount='一浴缸', temperature='40°')
相關文章
相關標籤/搜索