Django模型更新时修改BooleanField且创建时不触发的实现方案
实现方案
方案1:重写模型的save方法(最推荐,逻辑内聚)
直接在模型内部重写保存逻辑,判断当前是否为更新场景(主键已存在),符合要求时修改changed字段值:
from django.db import models class SomeModel(models.Model): changed = models.BooleanField(default=False, blank=True, null=True) # 你自己定义的其他字段... def save(self, *args, **kwargs): # 主键存在说明是更新已有的实例,而非新建 if self.pk is not None: # 若需要仅当其他字段实际变更时才修改changed,可追加字段变更判断逻辑 self.changed = True super().save(*args, **kwargs)
如果需要严格仅在其他字段真的发生修改时才把changed设为True,可调整save方法逻辑:
def save(self, *args, **kwargs): if self.pk is not None: original_instance = SomeModel.objects.get(pk=self.pk) # 遍历所有字段,排除changed本身,对比是否有变更 for field in self._meta.fields: if field.name != "changed" and getattr(self, field.name) != getattr(original_instance, field.name): self.changed = True break super().save(*args, **kwargs)
方案2:使用pre_save信号(适合解耦逻辑的场景)
如果不想把业务逻辑写在模型定义里,可以用Django的信号机制实现:
from django.db.models.signals import pre_save from django.dispatch import receiver from .models import SomeModel @receiver(pre_save, sender=SomeModel) def update_changed_flag(sender, instance, **kwargs): if instance.pk is not None: instance.changed = True
注意事项
- 上述两种方案仅在调用单个实例的
save()方法时生效,如果你使用QuerySet的批量更新方法(比如SomeModel.objects.filter(...).update(xxx=xxx)),不会触发单个实例的save方法和信号,需要手动在update参数里带上changed=True。 - 如果你使用Django自带的管理员后台修改模型实例,上述逻辑也可以正常生效。
内容的提问来源于stack exchange,提问作者nandesuka
相关产品推荐
相关产品推荐

