[ecmagnet][django] 如何使用django的signal

""" 
    在web開發中, 你可能會遇到下面這種場景:
    在用戶完成某個操做後, 自動去執行一些後續的操做. 譬如用戶完成修改密碼後,你要發送一份確認郵件

    觀察者模式:觀察者模式(Observer)完美的將觀察者和被觀察的對象分離開。
        舉個例子,用戶界面能夠做爲一個觀察者,業務數據是被觀察者,
        用戶界面觀察業務數據的變化,發現數據變化後,就顯示在界面上
"""

"""學習網站https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html"""

"""兩個重要的對象:Sender receiver 
         sender dispatch a signal, receiver receive signal and do something
         sender 是一個object, receiver是一個方法,或者對象的方法
         將sender和receiver關聯起來是經過signal dispatchers, 即Signal.connect()方法來關聯sender,receiver
"""


# post_save信號
""" 在mode對象執行save函數時,就會觸發該信號"""

from django.contrib.auth.models import User
from django.db.models.signals import post_save

def save_profile(sender, instance, **kwargs):
    instance.profile.save()

post_save.connect(save_profile, sender=User)


# save_profile是receiver,User是sender, post_save是signal, 上面代碼能夠理解成:當User對象執行save函數後,就會執行save_profile函數

# 若是去掉post_save.connect的sender參數,如: post_save.connect(save_profile), 則就是任意一個model執行了save函數,都會調用save_profile函數


"""關聯sender和receiver還能夠經過@receiver裝飾器來完成

def receiver(signal, **kwargs)"""
# 兩個參數,signal能夠是元組或者列表,或者單個信號
# **kwargs是位置參數,注意


from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save()




# 註冊信號不該該在app的models或者根目錄,django建議咱們將signals放到config裏面,如下面爲了,profile爲一個app;cmdbox是project


# profile/signals.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

from cmdbox.profiles.models import Profile

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

""" instance參數就是sender的實例化對象"""
    
    
#profiles/app.py:
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _

class ProfilesConfig(AppConfig):
    name = 'cmdbox.profiles'
    verbose_name = _('profiles')

    def ready(self):
        import cmdbox.profiles.signals  # noqa
        
# profiles/__init__.py: 若是已經在工程裏面註冊了app,這裏是不須要的
default_app_config = 'cmdbox.profiles.apps.ProfilesConfig'




# 若是是經過connect關聯sender和receiver,參考下面代碼

# profile/signals.py
from cmdbox.profiles.models import Profile

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

    
# profile/app.py
from django.apps import AppConfig
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _

from cmdbox.profiles.signals import create_user_profile, save_user_profile

class ProfilesConfig(AppConfig):
    name = 'cmdbox.profiles'
    verbose_name = _('profiles')

    def ready(self):
        post_save.connect(create_user_profile, sender=User)
        post_save.connect(save_user_profile, sender=User)

# profiles/__init__.py:
default_app_config = 'cmdbox.profiles.apps.ProfilesConfig'
View Code
相關文章
相關標籤/搜索