Django中字段变化触发的操作
我想知道,当我的模型中的某个字段发生变化时,如何触发一些操作。在这个例子中,我有一个模型:
class Game(models.Model):
STATE_CHOICES = (
('S', 'Setup'),
('A', 'Active'),
('P', 'Paused'),
('F', 'Finished')
)
name = models.CharField(max_length=100)
owner = models.ForeignKey(User)
created = models.DateTimeField(auto_now_add=True)
started = models.DateTimeField(null=True)
state = models.CharField(max_length=1, choices=STATE_CHOICES, default='S')
我希望在状态从“设置”变为“活动”时,创建单位,并且将“开始”字段填入当前的日期和时间(还有其他一些操作)。
我觉得可能需要一个模型实例的方法,但文档里似乎没有太多关于如何以这种方式使用它们的说明。
更新:我在我的游戏类中添加了以下内容:
def __init__(self, *args, **kwargs):
super(Game, self).__init__(*args, **kwargs)
self.old_state = self.state
def save(self, force_insert=False, force_update=False):
if self.old_state == 'S' and self.state == 'A':
self.started = datetime.datetime.now()
super(Game, self).save(force_insert, force_update)
self.old_state = self.state
8 个回答
20
Django 有一个很棒的功能叫做 信号,简单来说就是在特定的时刻触发的一些动作:
- 在模型的保存方法被调用之前或之后
- 在模型的删除方法被调用之前或之后
- 在发出 HTTP 请求之前或之后
想了解更多详细信息,可以去看看文档,但其实你只需要创建一个接收函数,并把它注册为信号。这通常是在 models.py 文件里完成的。
from django.core.signals import request_finished
def my_callback(sender, **kwargs):
print "Request finished!"
request_finished.connect(my_callback)
简单吧?
46
这个问题已经有人回答过了,不过我这里给你举个例子,讲讲怎么使用信号、post_init和post_save。
from django.db.models.signals import post_save, post_init
class MyModel(models.Model):
state = models.IntegerField()
previous_state = None
@staticmethod
def post_save(sender, instance, created, **kwargs):
if instance.previous_state != instance.state or created:
do_something_with_state_change()
@staticmethod
def remember_state(sender, instance, **kwargs):
instance.previous_state = instance.state
post_save.connect(MyModel.post_save, sender=MyModel)
post_init.connect(MyModel.remember_state, sender=MyModel)
23
基本上,你需要重写一下 save
方法,检查一下 state
字段有没有被修改,如果需要的话就设置 started
,然后让模型的基类继续把数据保存到数据库里。
比较棘手的部分是要弄清楚这个字段有没有被改动。可以看看这个问题中的 mixins 和其他解决方案,帮助你理解: