【问题标题】:How to auto-update update time in MongoEngine?如何在 MongoEngine 中自动更新更新时间?
【发布时间】:2020-03-30 09:21:58
【问题描述】:

我使用 flask-mongoEngine 创建了一些集合。例如,作者、书籍、公司等。相同的部分是他们有 2 个名为

的文件
created_at = db.DateTimeField(required=True, default=utcnow())
updated_at = db.DateTimeField(required=True, default=utcnow())

每次创建新文档时,我都需要更新 created_at 和 updated_at 的值,当我更新文档时,我需要更新 updated_at 的值。 有没有什么好办法,当我做 save() 操作时,这些时间字段可以自动更新?

【问题讨论】:

    标签: mongodb mongoengine flask-mongoengine


    【解决方案1】:

    使用括号将默认值设置为 utcnow() 会导致 Python 在创建类时执行 utcnow 函数,而不是在创建使用该类的新对象时执行。相反,您应该将默认设置为不带 () 的函数。这会将函数作为对象本身传递,而不是立即调用它,并且当从此类创建新对象时,该函数将执行。

    另外,Python 文档recommend using datetime.now over utcnow。随之而来的是,您的示例应如下所示:

    import datetime
    
    class Example(mongoengine.Document):
        created_at = db.DateTimeField(required=True, default=datetime.datetime.now)
        updated_at = db.DateTimeField(required=True, default=datetime.datetime.now)
    

    至于每次调用 save() 时更新 updated_at 属性,您可以为 save() 创建一个包装函数,将 updated_at 设置为 datetime.now(),然后保存。然后,不要调用 save(),而是在要保存时调用包装函数。

    包装函数是一个执行一些预处理然后调用另一个函数的函数(参见维基百科:https://en.wikipedia.org/wiki/Wrapper_function)。

    例如,你写一个这样的函数:

    def my_save(object):
        object.updated_at = datetime.datetime.now()
        return object.save()
    

    然后每当你想保存一个对象时,你调用 my_save() 而不是 object.save()。

    【讨论】:

    • 如何创建包装器和用法?如果可能的话,你能分享一下这个例子吗?
    • 我更新了我的帖子,提供了有关包装函数的更多信息。
    【解决方案2】:

    另一种选择是使用继承(假设您希望在一个模型中定义这两个字段):使用创建/更新的时间戳字段创建一个基类,覆盖 save 方法并继承您的文档类这个基类:

    import datetime
    
    class TimestampedDocument(Document):
    
        meta = {'allow_inheritance': True, 'abstract': True}
    
        created_at = DateTimeField(required=True, default=datetime.datetime.now)
        updated_at = DateTimeField(required=True, default=datetime.datetime.now)
    
        def save(
            self,
            force_insert=False,
            validate=True,
            clean=True,
            write_concern=None,
            cascade=None,
            cascade_kwargs=None,
            _refs=None,
            save_condition=None,
            signal_kwargs=None,
            **kwargs,
        ):
            self.updated = datetime.datetime.now()
            super().save(
                force_insert, validate, clean, write_concern, cascade, cascade_kwargs, _refs, save_condition,
                signal_kwargs, **kwargs
            )
    
    ...
    
    class YourDocument(TimestampedDocument):
        meta = {'collection': 'YourDocument'}
    

    在这种情况下,created_at 在创建文档时设置为一个,updated_at 会在您每次修改文档时更新。

    【讨论】:

    • 它正在使用TimestampedDocument 名称创建集合。我在派生类上明确指定了集合名称。
    • 您可以在元属性中指定集合名称 - 请参阅更新示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2012-03-22
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多