Django抽象模型中DateTimeField的auto_now_add=True失效、自定义save方法未触发及created字段更新异常问题求助
解决Django抽象模型Mixin的save方法未触发及created字段问题
我来帮你分析并搞定这两个问题:
问题根源拆解
- created字段空值报错:你用
if not self.id:判断是否是新建对象,但id字段设置了default=generate_unique_id——这意味着对象刚实例化时id就已经有值了,导致这个条件永远不成立,self.created = timezone.now()根本没执行。再加上created字段既没设auto_now_add=True也没默认值,数据库非空约束直接触发错误。 - save方法无打印输出:其实Mixin的save方法大概率被调用了,但因为
if not self.id:不满足,只有MODIFY WHILE UPDATE的打印,你误以为没触发。 - 更新时created被修改:之前的逻辑判断错误,可能在更新时误操作了created字段,我们需要用标准方式区分新建和更新场景。
解决方案
1. 修正TimeStampMixin逻辑,确保created字段正确赋值
把判断是否为新建对象的逻辑换成Django官方推荐的self._state.adding,同时给created字段加auto_now_add=True做兜底,避免意外情况。修改后的Mixin代码:
class TimeStampMixin(models.Model): id = models.CharField(max_length=60, editable=False, primary_key=True, default=generate_unique_id) # 新增auto_now_add=True作为兜底,同时保留自定义赋值逻辑 created = models.DateTimeField(editable=False, auto_now_add=True) modified = models.DateTimeField(auto_now=True) def save(self, *args, **kwargs): # 使用Django内置的状态判断是否为新建对象 if self._state.adding: print("SAVING WHILE CREATE") self.created = timezone.now() print("MODIFY WHILE UPDATE") self.modified = timezone.now() return super().save(*args, **kwargs) class Meta: abstract = True
2. 彻底阻止更新时修改created字段
上面的逻辑已经保证只有新建对象时才会设置created,更新时不会进入if self._state.adding:分支,自然不会修改created。再加上created字段设置了editable=False,在后台管理或表单里也无法手动修改,双重保障。
Sport模型无需修改
你的Sport模型的save方法是正确的,调用super()会正常触发Mixin的save逻辑,保持原代码即可:
class Sport(TimeStampMixin): name = models.CharField(max_length=100, unique=True) image = models.ImageField(upload_to=path_and_rename,null=True,blank=True) def __str__(self): return self.name def save(self, *args, **kwargs): self.name = self.name.upper() return super().save(*args, **kwargs)
额外提醒
- 如果你之前已经执行过迁移,需要生成新的迁移文件来更新
created字段的auto_now_add属性,确保数据库层面的约束匹配。 - 避免用
bulk_create批量创建对象,它会绕过模型的save方法,导致Mixin的时间戳逻辑失效。如果必须用,要手动给每个对象设置created和modified字段。
内容的提问来源于stack exchange,提问作者Saif
相关产品推荐
相关产品推荐

