国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Django使用Signals監測model字段變化發送通知的一些技巧

2020-01-04 14:02:22
字體:
來源:轉載
供稿:網友

本文將介紹工單通知實現過程中的一些小技巧。所有演示均基于Django2.0

閱讀此篇文章你可以:

  • 解鎖一個python if的使用新姿勢
  • 獲取一個利用signals做通知的真實案例
  •  

背景說明

先看看工單表簡化后的結構

class Ticket(models.Model):  '''工單表'''  STATE = (    (1, '待審批'),    (2, '已撤銷'),    (3, '已通過'),    (4, '被拒絕'),    (5, '已掛起'),    (6, '執行中'),    (7, '已完成'),    (8, '已失敗')  )  create_time = models.DateTimeField(auto_now_add=True, verbose_name='創建時間')  create_user = models.ForeignKey(User, on_delete=models.DO_NOTHING, verbose_name='創建用戶')  state = models.IntegerField(choices=STATE, default=1, verbose_name='工單狀態')

Ticket工單表有一個state字段標識當前工單狀態,這個狀態會隨著工單的進行而改變,每當工單狀態改變時就需要發送通知給相應的用戶,例如工單創建時,需要發送給創建者一個工單創建成功的通知,同時發送給審核者一個待審核的通知

通知

每一個狀態的變化都需要通知,為了代碼易讀及解耦,我們需要寫一個單獨的通知類,當需要通知的時候調用一下就好了。通知類中需要判斷當前工單的狀態,那么通常會寫成下邊這樣

class Notify:  def __init__(self):    self.dba_list = ["dba1@ops-coffee.cn", "dba2@ops-coffee.cn"]  def migration(self, pk):    '''遷移通知'''    _t = Ticket.objects.get(id=pk)    _u = _t.create_user.username    _s = _t.state    _d = "https://ops-coffee.cn/workflow/migration/%d/" % (_t.id)    if _s == 1:      try:        Email(          subject="[已提交]-[overmind]數據遷移工單",          content="你的數據遷移工單已提交,正在等待DBA審批,后續有狀態變更將會自動通知你。/r/n/r/n工單詳情:%s" % _d,          reciever_list=[_u]        )      except Exception as e:        print('Error:' + str(e))      try:        Email(          subject="[待審批]-[overmind]數據遷移工單",          content="你有工單需要審批,點擊下方工單詳情鏈接及時審批。/r/n/r/n工單詳情:%s" % _d,          reciever_list=self.dba_list        )      except Exception as e:        print('Error:' + str(e))    elif _s == 6:      try:        Email(          subject="[執行中]-[overmind]數據遷移工單",          content="數據遷移工單已通過DBA審核,正在執行中,后續有狀態變更將會自動通知你。/r/n/r/n工單詳情:%s" % _d,          reciever_list=[_u] + self.dba_list,        )      except Exception as e:        print('Error:' + str(e))    elif _s == 7:      try:        Email(          subject="[已完成]-[overmind]數據遷移工單",          content="數據遷移工單已自動完成遷移,請檢查最終狀態,如有任何疑問隨時聯系DBA。/r/n/r/n工單詳情:%s" % _d,          reciever_list=[_u] + self.dba_list,        )      except Exception as e:        print('Error:' + str(e))

以上的代碼可以看出來寫了很多重復的try代碼,并且當狀態越多,if判斷越復雜時重復的代碼也會越來越多,有沒有更簡潔的方式呢?

看看下邊的代碼,維護一個狀態字典,然后用一個if判斷就可以實現上邊一堆if的代碼寫法,是不是就簡潔了很多

class Notify:  def __init__(self):    self.dba_list = ["dba1@ops-coffee.cn", "dba2@ops-coffee.cn"]  def migration(self, pk):    '''遷移通知'''      _t = Ticket.objects.get(id=pk)    _u = _t.create_user.username    _s = _t.state      _d = "https://ops-coffee.cn/workflow/migration/%d/" %(_t.id)    smap = {      1: [{        "subject": "[已提交]-[overmind]數據遷移工單",        "content": "你的數據遷移工單已提交,正在等待DBA審批,后續有狀態變更將會自動通知你。/r/n/r/n工單詳情:%s" %_d,        "reciever_list": [_u],      }, {        "subject": "[待審批]-[overmind]數據遷移工單",        "content": "你有工單需要審批,點擊下方工單詳情鏈接及時審批。/r/n/r/n工單詳情:%s" %_d,        "reciever_list": self.dba_list,      }],      6: [{        "subject": "[執行中]-[overmind]數據遷移工單",        "content": "數據遷移工單已通過DBA審核,正在執行中,后續有狀態變更將會自動通知你。/r/n/r/n工單詳情:%s" %_d,        "reciever_list": [_u] + self.dba_list,      }],      7: [{        "subject": "[已完成]-[overmind]數據遷移工單",        "content": "數據遷移工單已自動完成遷移,請檢查最終狀態,如有任何疑問隨時聯系DBA。/r/n/r/n工單詳情:%s" %_d,        "reciever_list": [_u] + self.dba_list,      }]    }      _list = smap[_s]    for i in range(0, len(_list)):      try:        Email(          subject=_list[i]['subject'],           content=_list[i]['content'],           reciever_list=_list[i]['reciever_list']        )      except Exception as e:        print('Error:' +str(e))

在構造字典的時候采用了狀態做key,通知變量做value,同時一個狀態可能會產生多個不同的通知,所以value采用列表的方式,這樣即可輕松實現一個狀態多條通知,每條通知都可以發給不同的人,有不同的主題,不同的內容。

Signals

上邊我們已經寫好了發送通知的類,在view里每次修改工單狀態之后調用下通知類即可實現通知發送,但這樣通知跟view強耦合,且通知會分散在view中的多個地方,造成代碼冗余且不夠優雅。我們需要一個簡單優雅的方式來實現,signals可以說是非常有用了

Signals是Django自帶的一個信號調度程序。如果你對svn或者git之類的hooks有了解,這個理解起來就簡單多了,通俗來說就是當你的程序產生一個事件時,會通過signals自動觸發其他的事件。就比如我們這個工單系統通知,當工單狀態產生變化時自動發送郵件給相關人。

Django內部已經定義好了一些signal供我們使用,如果不能滿足我們也可以自定義signal,其中Django內部定義的signal主要分為幾類

model signalspre_initpost_initpre_savepost_savepre_deletepost_deletem2m_changedclass_preparedmanagement signalspre_migratepost_migraterequest/response signalsrequest_startedrequest_finishedgot_request_exceptiontest signalssetting_changedtemplate_renderedDatabase Wrappersconnection_created :連接建立時觸發

那么信號究竟該如何使用呢?下邊一個實際的例子來說明下信號的使用

就以我們發送通知的需求為例,workflow是一個普通的app,第一步需要新建 workflow/signals.py 文件綁定signal

from django.db.models import signalsfrom django.dispatch import receiverfrom workflow.models import Ticketfrom workflow.backends.notify import Notify@receiver(signals.post_init, sender=Ticket)def migrate_notify_init(instance, **kwargs):  instance.old_state = instance.state@receiver(signals.post_save, sender=Ticket)def migrate_notify_post(instance, created, **kwargs):  if created or instance.old_state != instance.state:    Notify().migration(instance.id)

這里用到了兩個signal, post_init 和 post_save

在model初始化之后通過 post_init 信號獲取到state的值作為初始狀態值,在每次model執行save方法后調用 post_save 信號獲取到新的狀態值,對兩次狀態值做比較如果不一致則表示狀態有更新發送通知

是上邊的判斷只能判斷到狀態變更了發通知,但工單在第一次創建時old_state和state是一樣的,所以也需要在save之后判斷下這次操作是不是新建,如果是新建同樣需要發送通知

第二步加載signal,需要修改兩個配置文件

config1: workflow/apps.pyfrom django.apps import AppConfigclass WorkflowConfig(AppConfig):  name = 'workflow'  def ready(self):    import workflow.signalsconfig2: workflow/__init__.pydefault_app_config = 'workflow.apps.WorkflowConfig'

綁定成功后就可以在每次工單狀態發生變化時發送郵件了

總結

以上所述是小編給大家介紹的Django使用Signals監測model字段變化發送通知的一些技巧,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


注:相關教程知識閱讀請移步到python教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 荔波县| 运城市| 怀远县| 称多县| 营山县| 丰城市| 桃园县| 玛曲县| 岑巩县| 赤壁市| 吉安县| 昌乐县| 乌鲁木齐县| 新河县| 抚远县| 铜鼓县| 正镶白旗| 玛多县| 瑞丽市| 泸溪县| 大渡口区| 登封市| 西青区| 陇川县| 社会| 鱼台县| 布尔津县| 利川市| 铜梁县| 叙永县| 海兴县| 建平县| 开封县| 密山市| 嫩江县| 工布江达县| 静宁县| 海盐县| 阆中市| 托克逊县| 通江县|