程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Django signals 信號總結

編輯:Python

故事背景

最近在做的項目中都遇到使用 django 信號量,故此總結信號相關的使用。

什麼是信號

Django 中內置一個 信號調度器,它可以幫助應用程序在框架中的其他地方發生某些固定操作時能夠得到通知。簡而言之:信號允許某些發送器通知一組接收器某些操作已經發生。當接受器接受到這一通知時可以做響應的處理。

Django 中內置的信號集

模型信號

  • 模型初始化時

    • django.db.models.signals.pre_init(模型在初始化時發出)
    • django.db.models.signals.post_init(模型在被初始化之後發出)
  • 模型 save()方法相關信號

    • django.db.models.signals.pre_save (模型在被保存之前發出)
    • django.db.model.signals.post_save(模型對象被保存之後發出)
  • 模型 delete()方法相關信號

    • dajngo.db.models.signals.pre_delete(模型被刪除之前)
    • django.db.models.signals.post_delete(模型被刪除之後)
  • 模型多對多(manytomanyField)字段發生更改時

    • django.db.models.signals.m2m_changed(模型中多對多字段發生改變)
  • 執行遷移之前

    • django.db.models.signals.pre_migrate(在模型遷移之前執行)
    • django.db.models.signals.post_migrate(在模型遷移之後執行)

網絡請求相關

  • django 發起或者結束一個 http 請求相關信號
    • django.core.signals.request_started(django 發起一個 http 請求前)
    • django.core.signals.request_finished(django 發起一個 http 請求之後)
  • django 發送請求發生錯誤時
    • django.core.signals.got_request_exception(發送請求發生錯誤時)

Django 信號量使用

使用 Signal.connect()方法注冊一個接收器函數,當發送信號時調用接收器。信號的所有接收器函數都會按照注冊時的順序一個接一個調用。

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

  • receiver:將連接到此信號的回調函數
  • sender:指定要從其接收信號的特定發送方
  • weak:Django 默認將信號處理程序存儲為弱引用,因此如果你的接收器函數時本地函數,則可能會對其進行垃圾回收。如果想避免這種情況發生可以當你要調用 connct() 方法時傳入 weak=False
  • disptch_uid:在可能發送重復信號的情況下,信號接收器的唯一標識

接受信號函數

下面我們定義一個接收函數,接受函數可以是任何 python 函數或者方法:

def my_callback(sender, **kwargs):
print('hello world')

注意️:該函數接受一個 sneder 參數以及關鍵字參數(**kwargs),所有信號處理程序都必須接受這些參數。

連接接受函數

Django 提供兩種方法可以將接收器連接到信號。

  • 方式一:Signal.connet(my_callback)

    from django.core.signals import request_finished
    request_finished.connect(my_callback)
    
  • 方式二:receiver(sigal)

    • 參數 signal:一個用於連接函數的信號包含多個信號列表
    • 接受函數和連接接受函數放在 在一起
    from django.core.signals import request_finished
    from django.dispatch import receiver
    @receiver(request_finished)
    def my_callback(sender, **kwargs):
    print('hello world')
    

    以上兩種方式都能到達 my_callback 函數在每次請求完成時被調用

接受到特定發送器發送的信號

在某些情況下有些信號被發送多次,但你只對這些信號中某部分信號感興趣。假設我們有 User 以及 Enterprise 兩個 model 我們只想接受當模型 User 保存後的信號,代碼如下:

from django.db.models.signals import post_save
from django.dispatch import receiver
from . models import User
@receiver(post_save, sender=Udser)
# 這裡的 instance 可以表示為當前變化的模型實例
def my_handel(sender, instance, **kwargs):
# to do ...

防止信號重復

在某些情況下,接受器可能同時接受相同信號多次,這可能會導致接收函數被注冊多次,因此對於一個信號時間調用同樣多次,為防止這種相同信號被接受多次的情況發生,我們可以傳遞一個唯一標識符作為 dispatch_uid 參數來標識接收方函數。這個標識符通常是一個字符串,對於每個唯一 dispatch_uid 值,接受器函數值與信號綁定一次:

from django.core.signals import post_save
post_save.connect(my_callback, dispatch_uid='my_unique_identifier')

django 信號量實際使用

監聽某個模型中某個字段的變化

假設我們有一個 User 模型,當我們用戶名發生改變時需要重置 token,這時我們只需要監聽 User 中 token 是否變化,如果變化則重置 token,使用信號來實現這一需求

# 用戶模型
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=32, verbose_name='用戶名')
areaCode = models.CharField(max_length=10, blank=True, verbose_name='手機區號')
phone = models.CharField(max_length=20, verbose_name='用戶手機號', blank=True)
email = models.EmailField(max_length=50, verbose_name='用戶郵箱', blank=True)
avatar = models.CharField(max_length=255, verbose_name='用戶頭像')
token = models.CharField(max_length=50, verbose_name='token')
# 信號量實現以上場景
from django.db.models.signals import post_init, post_save
from django.dispatch import receiver
from . models import User
@receiver(post_init, sender=User)
def init_signal(sender, instance, **kwargs):
# 在模型初始化時將 name 賦值給 __origin_name
instance.__origin_name = instance.name
@receiver(post_save, sender=User)
def save_signal(sender, instance, **kwargs):
# 當模型被保存時查看此時的 name 和 __origin_name 是否相等,如果不相等則重置 token
if instance.__origin_name and instance.__origin_name != instance.name:
# 重置 token

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved