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

如何在Flask-MongoEngine中自动更新文档时间字段?

自动更新Flask-MongoEngine文档的时间字段

当然有办法啦!在Flask-MongoEngine里,我们有两种很实用的方式来实现自动更新created_at和updated_at的需求,再也不用每次手动设置时间啦~

方法一:自定义抽象基础模型(推荐)

这种方式最优雅,我们可以创建一个抽象的基础模型类,把时间字段和自动更新逻辑都放在里面,其他业务模型直接继承它就好,避免重复代码。

from flask_mongoengine import MongoEngine
from datetime import datetime, timezone

db = MongoEngine()

# 定义抽象基础模型,不会生成实际集合
class BaseDocument(db.Document):
    created_at = db.DateTimeField(required=True)
    updated_at = db.DateTimeField(required=True)

    meta = {'abstract': True}

    def save(self, *args, **kwargs):
        now = datetime.now(timezone.utc)
        # 新文档时设置created_at
        if not self.created_at:
            self.created_at = now
        # 无论新增还是更新,都刷新updated_at
        self.updated_at = now
        # 调用父类的save方法完成保存
        return super().save(*args, **kwargs)

# 业务模型直接继承BaseDocument即可
class Author(BaseDocument):
    name = db.StringField(required=True)

class Book(BaseDocument):
    title = db.StringField(required=True)
    author = db.ReferenceField(Author)

class Company(BaseDocument):
    name = db.StringField(required=True)

这样不管是创建新文档(Author(name="张三").save())还是更新已有文档(author.name="李四"; author.save()),时间字段都会自动被正确设置。

方法二:使用MongoEngine的预保存信号

如果你不想修改模型的继承关系,或者需要给已有的模型添加自动更新逻辑,可以用MongoEngine提供的pre_save信号——它会在文档保存前触发,我们可以在这个时机更新时间字段。

from flask_mongoengine import MongoEngine
from mongoengine import signals
from datetime import datetime, timezone

db = MongoEngine()

# 定义你的业务模型
class Author(db.Document):
    name = db.StringField(required=True)
    created_at = db.DateTimeField(required=True)
    updated_at = db.DateTimeField(required=True)

class Book(db.Document):
    title = db.StringField(required=True)
    author = db.ReferenceField(Author)
    created_at = db.DateTimeField(required=True)
    updated_at = db.DateTimeField(required=True)

class Company(db.Document):
    name = db.StringField(required=True)
    created_at = db.DateTimeField(required=True)
    updated_at = db.DateTimeField(required=True)

# 定义信号处理函数
def update_timestamps(sender, document, **kwargs):
    now = datetime.now(timezone.utc)
    if not document.created_at:
        document.created_at = now
    document.updated_at = now

# 给每个模型注册pre_save信号
signals.pre_save.connect(update_timestamps, sender=Author)
signals.pre_save.connect(update_timestamps, sender=Book)
signals.pre_save.connect(update_timestamps, sender=Company)

注意事项

  • 两种方法都是针对save()方法生效的,如果直接使用update()或update_one()这类数据库层面的更新操作,不会触发模型的save()方法或pre_save信号,这时候需要手动在更新语句里指定updated_at的值。
  • 不要给created_at和updated_at设置默认值(比如default=utcnow()),否则可能会和自动更新逻辑产生冲突,让代码逻辑来控制时间字段的值更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 08:22:39