古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。

Django使用Signals监测model字段变化发送通知

Python admin 171℃ 0评论

背景说明

先看看工单表简化后的结构

Ticket工单表有一个state字段标识当前工单状态,这个状态会随着工单的进行而改变,每当工单状态改变时就需要发送通知给相应的用户,例如工单创建时,需要发送给创建者一个工单创建成功的通知,同时发送给审核者一个待审核的通知

通知

每一个状态的变化都需要通知,为了代码易读及解耦,我们需要写一个单独的通知类,当需要通知的时候调用一下就好了。通知类中需要判断当前工单的状态,那么通常会写成下边这样

以上的代码可以看出来写了很多重复的try代码,并且当状态越多,if判断越复杂时重复的代码也会越来越多,有没有更简洁的方式呢?

看看下边的代码,维护一个状态字典,然后用一个if判断就可以实现上边一堆if的代码写法,是不是就简洁了很多

在构造字典的时候采用了状态做key,通知变量做value,同时一个状态可能会产生多个不同的通知,所以value采用列表的方式,这样即可轻松实现一个状态多条通知,每条通知都可以发给不同的人,有不同的主题,不同的内容。

Signals

上边我们已经写好了发送通知的类,在view里每次修改工单状态之后调用下通知类即可实现通知发送,但这样通知跟view强耦合,且通知会分散在view中的多个地方,造成代码冗余且不够优雅。我们需要一个简单优雅的方式来实现,signals可以说是非常有用了

Signals是Django自带的一个信号调度程序。如果你对svn或者git之类的hooks有了解,这个理解起来就简单多了,通俗来说就是当你的程序产生一个事件时,会通过signals自动触发其他的事件。就比如我们这个工单系统通知,当工单状态产生变化时自动发送邮件给相关人。

Django内部已经定义好了一些signal供我们使用,如果不能满足我们也可以自定义signal,其中Django内部定义的signal主要分为几类

  1. model signals
    • pre_init:model初始化前触发
    • post_init:model初始化后触发
    • pre_save:save()方法前触发
    • post_save:save()方法后触发
    • pre_delete:delete()方法前触发
    • post_delete:delete()方法后触发
    • m2m_changed:ManyToManyField字段改变时触发
    • class_prepared:没用过字面意思理解吧
  2. management signals
    • pre_migrate:migrate之前触发
    • post_migrate:migrate之后触发
  3. request/response signals
    • request_started:请求开始时触发
    • request_finished:请求完成后触发
    • got_request_exception:请求异常时触发
  4. test signals
    • setting_changed:配置改变时触发
    • template_rendered:模板渲染时触发
  5. Database Wrappers
    • connection_created:连接建立时触发

那么信号究竟该如何使用呢?下边一个实际的例子来说明下信号的使用

就以我们发送通知的需求为例,workflow是一个普通的app,第一步需要新建workflow/signals.py文件绑定signal

这里用到了两个signal,post_initpost_save

在model初始化之后通过post_init信号获取到state的值作为初始状态值,在每次model执行save方法后调用post_save信号获取到新的状态值,对两次状态值做比较如果不一致则表示状态有更新发送通知

是上边的判断只能判断到状态变更了发通知,但工单在第一次创建时old_state和state是一样的,所以也需要在save之后判断下这次操作是不是新建,如果是新建同样需要发送通知

第二步加载signal,需要修改两个配置文件

config1:workflow/apps.py

config2:workflow/__init__.py

绑定成功后就可以在每次工单状态发生变化时发送邮件了.

转自 https://juejin.im/post/5bf2189ee51d4549fb34ab17

转载请注明:北凉柿子 » Django使用Signals监测model字段变化发送通知

喜欢 (0)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址