""" 在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'