最近在做的項目中都遇到使用 django
信號量,故此總結信號相關的使用。
Django 中內置一個 信號調度器
,它可以幫助應用程序在框架中的其他地方發生某些固定操作時能夠得到通知。簡而言之:信號允許某些發送器通知一組接收器某些操作已經發生。當接受器接受到這一通知時可以做響應的處理。
模型初始化時
模型 save()方法相關信號
模型 delete()方法相關信號
模型多對多(manytomanyField)字段發生更改時
執行遷移之前
使用 Signal.connect()方法注冊一個接收器函數,當發送信號時調用接收器。信號的所有接收器函數都會按照注冊時的順序一個接一個調用。
Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)
下面我們定義一個接收函數,接受函數可以是任何 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)
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')
假設我們有一個 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