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

Flask中SQLAlchemy多列时间戳插入不一致的解决方法

Flask-SQLAlchemy 中统一插入时间戳的正确处理方式

问题原因

当前模型同时设置了 default=datetime.utcnow 和 server_default=func.now(),其中 datetime.utcnow 是Python本地函数,创建实例时会被分别调用两次(为inserted_at和modified_at赋值),两次调用的时间差导致了毫秒级差异。若仅保留server_default,数据库会生成统一的时间戳,但未提交的模型实例无法获取该值——因为server_default是数据库层面生成的,ORM不会自动同步到未提交的实例中。

解决方案

方案一:重写模型初始化方法,统一赋值时间戳

在模型的__init__方法中生成一个单一的UTC时间,同时赋值给两个时间字段,确保创建实例时就拥有一致的时间值,且提交到数据库时保持一致。

from datetime import datetime
from your_app import db

class RenterLead(BaseModel):
    __tablename__ = "renter_leads"

    uuid = db.Column(db.String, nullable=False, primary_key=True)
    owner = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    name = db.Column(db.String)
    email = db.Column(db.String)
    phone_number = db.Column(db.String)
    inserted_at = db.Column(db.DateTime, nullable=False)
    modified_at = db.Column(db.DateTime, nullable=False)

    def __init__(self, **kwargs):
        current_time = datetime.utcnow()
        # 若未传入时间字段,则使用统一生成的时间
        kwargs.setdefault('inserted_at', current_time)
        kwargs.setdefault('modified_at', current_time)
        super().__init__(**kwargs)

方案二:使用SQLAlchemy事件监听,插入前统一设置时间

通过SQLAlchemy的before_insert事件监听,在记录插入到数据库之前,为两个时间字段赋值同一个UTC时间,既保证数据库中时间一致,也能让实例在插入前拥有时间值。

from datetime import datetime
from sqlalchemy import event
from your_app import db

class RenterLead(BaseModel):
    __tablename__ = "renter_leads"

    uuid = db.Column(db.String, nullable=False, primary_key=True)
    owner = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    name = db.Column(db.String)
    email = db.Column(db.String)
    phone_number = db.Column(db.String)
    inserted_at = db.Column(db.DateTime, nullable=False)
    modified_at = db.Column(db.DateTime, nullable=False)

@event.listens_for(RenterLead, 'before_insert')
def set_unified_timestamps(mapper, connection, target):
    current_time = datetime.utcnow()
    target.inserted_at = current_time
    target.modified_at = current_time

补充:仅用数据库生成时间(适合可接受提交后获取值的场景)

如果可以接受未提交实例无时间值,仅保留server_default=func.now(),提交后调用session.refresh()同步数据库生成的时间值,此时两个字段时间完全一致。

from sqlalchemy import func
from your_app import db

class RenterLead(BaseModel):
    __tablename__ = "renter_leads"

    uuid = db.Column(db.String, nullable=False, primary_key=True)
    owner = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
    name = db.Column(db.String)
    email = db.Column(db.String)
    phone_number = db.Column(db.String)
    inserted_at = db.Column(db.DateTime, nullable=False, server_default=func.now())
    modified_at = db.Column(db.DateTime, nullable=False, server_default=func.now())

# 使用示例
lead = RenterLead(uuid="unique-uuid", owner=1)
db.session.add(lead)
db.session.commit()
# 同步数据库生成的时间到实例
db.session.refresh(lead)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:23:10