Django - 信號

Django - 信號

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

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

一. 模型信號

Model signals
    pre_init                    # django的modal執行其構造方法前,自動觸發
    post_init                   # django的modal執行其構造方法後,自動觸發
    pre_save                    # django的modal對象保存前,自動觸發
    post_save                   # django的modal對象保存後,自動觸發
    pre_delete                  # django的modal對象刪除前,自動觸發
    post_delete                 # django的modal對象刪除後,自動觸發
    m2m_changed                 # django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發
    class_prepared              # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發
    Management signals
    pre_migrate                 # 執行migrate命令前,自動觸發
    post_migrate                # 執行migrate命令後,自動觸發
    Request/response signals
    request_started             # 請求到來前,自動觸發
    request_finished            # 請求結束後,自動觸發
    got_request_exception       # 請求異常後,自動觸發
    Test signals
    setting_changed             # 使用test測試修改配置文件時,自動觸發
    template_rendered           # 使用test測試渲染模板時,自動觸發
    Database Wrappers
    connection_created          # 建立數據庫鏈接時,自動觸發

pre_init

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

帶有此信號的參數:後端

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

例如:服務器

from app01 import models

p = models.Publisher(name='帥氣的輝哥')

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

sender: Publisher(類自己)
ARGS:   [](一個空列表,由於沒有位置參數傳__init__()。)
kwargs: {'name': '帥氣的輝哥'}

pre_save

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

帶有此信號的參數:ide

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
django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發

在模型實例上更改了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
程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發

每當模型類「準備」時發送 - ,一旦模型已經被定義並在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 _except ###

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

帶有此信號的參數:

sender
處理程序類,如上。

request
HttpRequest對象。

四. 測試信號

信號只在running tests時發送。

setting_changet

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
打開的數據庫鏈接。 這能夠在多數據庫配置中使用,以區分來自不一樣數據庫的鏈接信號。

六. 使用信號

Rcceiver函數

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°')
相關文章
相關標籤/搜索