Djang字段更改触发的操作

2024-04-28 21:27:09 发布

您现在位置:Python中文网/ 问答频道 /正文

当我的一个模型中的某个字段发生更改时,如何使操作发生?在这种情况下,我有一个模型:

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

Tags: 模型selfgametruemodelslengthnowold
3条回答

Django有一个叫做signals的漂亮特性,它是在特定时间触发的有效触发器:

  • 调用模型的save方法之前/之后
  • 调用模型的delete方法之前/之后
  • 在发出HTTP请求之前/之后

阅读文档获取完整信息,但您只需创建一个接收器函数并将其注册为信号。这通常在models.py中完成。

from django.core.signals import request_finished

def my_callback(sender, **kwargs):
    print "Request finished!"

request_finished.connect(my_callback)

很简单,嗯?

它已经得到了回答,但是这里有一个使用信号的例子,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, **kwargs):
        instance = kwargs.get('instance')
        created = kwargs.get('created')
        if instance.previous_state != instance.state or created:
            do_something_with_state_change()

    @staticmethod
    def remember_state(sender, **kwargs):
        instance = kwargs.get('instance')
        instance.previous_state = instance.state

post_save.connect(MyModel.post_save, sender=MyModel)
post_init.connect(MyModel.remember_state, sender=MyModel)

基本上,您需要重写save方法,检查state字段是否已更改,如果需要,设置started,然后让模型基类完成对数据库的持久化。

最棘手的是弄清楚这个领域是否被改变了。查看此问题中的mixin和其他解决方案,以帮助您解决此问题:

相关问题 更多 >