如何在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
相关产品推荐
相关产品推荐

