You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django模型的save方法中判断state字段是否发生变更?

Django模型save方法中判断state字段变更的正确实现

问题场景

你定义了如下Django模型:

class Exam(BaseModel):
    ...
    STATE_CHOICES = (
        (PASS, PASS),
        (FAILED, FAILED),
        (GREAT, GREAT),
    )
    state = models.CharField(max_length=15, choices=STATE_CHOICES, default=PASS)
    ...

想要重写模型的save方法判断state字段是否变更,尝试的代码中self.__state写法错误,需要正确的实现方式。

错误原因

self.__state是Django模型内部的ModelState对象,用于跟踪实例的状态(比如是否为新建对象、是否已被删除等),并非字段的原始值,所以不能用它来比较字段是否变更。

正确实现方式

方法1:查询数据库获取原始值(简单直接)

通过查询数据库获取已存在对象的原始state值,和当前值比较:

def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    # 仅对已存在的对象(非新建)做判断
    if not self._state.adding:
        # 从数据库获取原始state值
        original_state = Exam.objects.get(pk=self.pk).state
        if original_state != self.state:
            print('state字段已变更')
    # 调用父类save方法完成保存
    super().save(force_insert, force_update, using, update_fields)

注意:这种方法会额外发起一次数据库查询,适合对性能要求不高的场景。

方法2:初始化时保存原始值(避免额外查询)

在模型初始化时保存state的原始值,后续直接比较:

class Exam(BaseModel):
    ...
    STATE_CHOICES = (
        (PASS, PASS),
        (FAILED, FAILED),
        (GREAT, GREAT),
    )
    state = models.CharField(max_length=15, choices=STATE_CHOICES, default=PASS)
    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 保存实例初始化时的state原始值
        self._original_state = self.state

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        # 仅对已存在的对象做变更判断
        if not self._state.adding and self._original_state != self.state:
            print('state字段已变更')
            # 这里可以添加字段变更后的业务逻辑
        # 完成保存
        super().save(force_insert, force_update, using, update_fields)
        # 更新原始值,避免后续保存时误判
        self._original_state = self.state

注意:如果通过QuerySet.update()方法批量更新字段,模型的save方法不会被触发,这种场景需要使用pre_save信号来处理。


内容的提问来源于stack exchange,提问作者Mehdi Aria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:34:43