1. 程式人生 > 其它 >【Django雜記】 Django Signals訊號的使用

【Django雜記】 Django Signals訊號的使用

1、訊號有哪些
  • Model_Signals
    • pre_init:Django中的model物件執行其構造方法前,自動觸發
    • post_init:Django中的model物件執行其構造方法後,自動觸發
    • pre_save:Django中的model物件儲存前,自動觸發
    • post_save:Django中的model物件儲存後,自動觸發
    • pre_delete:Django中的model物件刪除前,自動觸發
    • post_delete:Django中的model物件刪除後,自動觸發
    • m2m_changed:Django中的model物件使用m2m欄位操作資料庫的第三張表(add,remove,clear,update),自動觸發
    • class_prepared:程式啟動時,檢測到已註冊的model類,對於每一個類,自動觸發
  • Managemeng_sinals
    • pre_migrate:執行migrate命令前,自動觸發
    • post_migrate:執行migrate命令後,自動觸發
  • Request/Response_signals
    • request_started:請求到來前,自動觸發
    • request_finished:請求結束後,自動觸發
    • got_request_exception:請求異常時,自動觸發
  • Test_signals
    • setting_changed:配置檔案改變時,自動觸發
    • template_rendered:模型執行渲染操作時,自動觸發
  • Database_Wrapperd
    • connection_created:建立資料庫連線時,自動觸發

2、內建訊號如何使用呢?

  • 場景:
    • 有如下場景,我有一個Model名為Alert,表示一條告警,我需要在建立一個告警後進行郵件通知,怎麼實現呢?
  • 常規實現:
    • Alert類加一個表示欄位is_notify表示是否通過過,然後建立一個command,在後臺定時讀取Alert裡未通知的記錄:
for alert in Alert.objects.filter(is_notify = False):
    # 發郵件
    alert.is_notify = True
  • 缺點:
    • 需要建立一個後臺程序
    • 需要增加一個欄位標識是否通過
    • 後臺程序的維護,如掛掉了,那麼郵件通知不就終止了...
  • 使用訊號呢?
@receiver(post_save, sender=Alert)
def alert_notify(sender, instance, created, **kwargs):
    if created:
        # 傳送郵件
    return
  • 使用的方法:
    • 1、在自己的應用app下的init.py檔案中:[假設我有一個名為tongjiapp的應用]
default_app_config = "tongjiapp.apps.TongjiappConfig"
    • 2、在自己應用的app下的apps.py檔案中:
from django.apps import AppConfig

class TongjiappConfig(Appconfig):
    name = "tongjiapp"
    
    def ready(self):
        # 匯入訊號py檔案
        import tongjiapp.signals.async_script_signals
    • 3、在async_script_sinals中程式碼如下:
from django.db.models.signals import post_migrate
from django.dispatch import receiver

@receiver(post_migrate)
def init_script(sender, **keargs):
    print("我執行了")
    # 操作

3、訊號引數

  • pre_init
    • django.db.models.signals.pre_init
    • 每當你例項化Django模型時,該訊號都會在模型的__init__()方法的開頭髮送
    • 引數:
      • sender:剛建立了一個例項的模型類
      • args:傳遞給__init__()的位置引數列表
      • kwargs:傳遞給__init__()的關鍵字引數的字典
  • pre_save
    • django.db.models.signals.pre_save
    • 這是在模型的save()方法的開頭髮送的
    • 引數:
      • 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__(),注意不要匯入模型或觸發對應用程式登錄檔的呼叫
    • 引數:
      • send: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:遷移計劃將用於遷移執行,雖然該計劃不是公共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:遷移計劃將用於遷移執行,雖然該計劃不是公共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物件
測試訊號
  • 訊號只在runing 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:開啟的資料庫連線。這可以在多資料庫配置中使用,以區分來自不同資料庫的連線訊號。
文章摘自與:https://www.cnblogs.com/liwenzhou/p/9745331.html