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。
解决方法
获取数据库中已存在的实例:
使用Django ORM的查询方法从数据库加载数据,而非直接实例化:quotation = Quotation.objects.get(id=1) print(quotation.created_at) # 会返回数据库中存储的时间值新创建实例并获取时间值:
新实例必须调用save()方法完成数据库写入后,才能获取到自动设置的时间值:quotation = Quotation(reference="demo") quotation.save() print(quotation.created_at) # 此时会返回创建时间
补充:替代代码能运行的原因
你提供的替代代码使用了default=timezone.now,这个参数的逻辑是在实例化对象时就生成默认值(除非显式指定字段值),因此即使不保存,实例的时间字段也会有初始值。而自定义的AutoDateTimeField重写了pre_save方法,确保保存时更新updated_at,进一步保证了字段值的有效性。
内容的提问来源于stack exchange,提问作者nolwww
相关产品推荐
相关产品推荐

