如何在数据库层面强制Django模型自动生成时间戳
解决方案
方案1:使用__init_subclass__自动为所有子类注册触发器
直接在抽象模型的__init_subclass__方法中,给每个继承的非抽象子类自动注册触发器,无需逐个手动添加:
import pgtrigger from django.db import models class AbstractAppendOnly(models.Model): created_at = models.DateTimeField(auto_now=True, editable=False) db_note = models.TextField(default=None, null=True) class Meta: abstract = True def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) # 仅为实际生成数据库表的非抽象模型注册触发器 if not cls._meta.abstract: pgtrigger.register( pgtrigger.Trigger( name='insert_auto_created_at_timestamp', operation=pgtrigger.Insert, when=pgtrigger.Before, func=''' new.created_at = now(); return new; ''' ) )(cls)
该方案无额外侵入性,所有继承AbstractAppendOnly的业务模型会自动获得数据库层的时间戳强制逻辑,不会再出现抽象类无对应数据表的报错。
方案2:直接配置字段数据库级默认值(Django 3.2+支持)
Django 3.2及以上版本已原生支持db_default参数,可以直接在字段定义时设置数据库层面的默认值,无需触发器也无需自定义迁移,实现更轻量:
from django.db import models class AbstractAppendOnly(models.Model): # db_default会自动在表结构中添加DEFAULT约束 created_at = models.DateTimeField(auto_now=True, editable=False, db_default=models.functions.Now()) db_note = models.TextField(default=None, null=True) class Meta: abstract = True
生成迁移时会自动在CREATE TABLE语句中给created_at字段添加DEFAULT CURRENT_TIMESTAMP约束,完美满足数据库层面强制时间戳的要求。如果使用的Django版本低于3.2,建议升级后使用该方案,复杂度远低于触发器方案。
内容的提问来源于stack exchange,提问作者exilour
相关产品推荐
相关产品推荐

