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

Django抽象模型字段返回None问题排查

问题:Django抽象模型继承后时间字段返回None

我定义了一个Django抽象模型Trackable,包含created_at(auto_now_add=True)和updated_at(auto_now=True)字段,但继承该模型的Quotation实例的这两个字段均返回None,相关代码如下:

from django.db import models

class Trackable(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Quotation(Trackable):
    reference = models.CharField(null=True, max_length=80)

quotation = Quotation(id=1)
print(quotation.created_at)
>>> None

补充说明:以下代码可正常运行,但无法解释原代码的问题:

from django.db import models
from django.utils import timezone

class AutoDateTimeField(models.DateTimeField):
    def pre_save(self, model_instance, add):
        return timezone.now()

class Trackable(models.Model):
    created_at = models.DateField(default=timezone.now)
    updated_at = AutoDateTimeField(default=timezone.now)

    class Meta:
        abstract = True

class Quotation(Trackable):
    reference = models.CharField(null=True, max_length=80)

原因与解决方法

核心原因

auto_now_add=True和auto_now=True的生效逻辑是仅在模型实例被保存到数据库时自动赋值:

  • auto_now_add:仅在第一次保存(创建记录)时设置当前时间
  • auto_now:每次保存(更新记录)时设置当前时间

你直接通过Quotation(id=1)创建的是内存中的空对象,既没有从数据库读取已有数据,也没有执行保存操作,因此这两个字段不会被赋值,自然返回None。

解决方法

  1. 获取数据库中已存在的实例:
    使用Django ORM的查询方法从数据库加载数据,而非直接实例化:

    quotation = Quotation.objects.get(id=1)
    print(quotation.created_at)  # 会返回数据库中存储的时间值
    
  2. 新创建实例并获取时间值:
    新实例必须调用save()方法完成数据库写入后,才能获取到自动设置的时间值:

    quotation = Quotation(reference="demo")
    quotation.save()
    print(quotation.created_at)  # 此时会返回创建时间
    

补充:替代代码能运行的原因

你提供的替代代码使用了default=timezone.now,这个参数的逻辑是在实例化对象时就生成默认值(除非显式指定字段值),因此即使不保存,实例的时间字段也会有初始值。而自定义的AutoDateTimeField重写了pre_save方法,确保保存时更新updated_at,进一步保证了字段值的有效性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 02:50:30