33

我正在尝试为creation_time我的文档添加一个属性。下面是一个例子:

import datetime

class MyModel(mongoengine.Document):
    creation_date = mongo.DateTimeField()
    modified_date = mongo.DateTimeField(default=datetime.datetime.now)

Django 模型为其DateTimeField对象(如add_now等)内置了参数,但 MongoEngine 不支持这一点。

我想知道最好的方法是否如下:

m,created = MyModel.objects.get_or_create()
if created:
    m.creation_date = datetime.datetime.now()

或者如果有更好,更好的方法。

4

9 回答 9

74

您可以覆盖保存方法。

class MyModel(mongoengine.Document):
    creation_date = mongo.DateTimeField()
    modified_date = mongo.DateTimeField(default=datetime.datetime.now)

    def save(self, *args, **kwargs):
        if not self.creation_date:
            self.creation_date = datetime.datetime.now()
        self.modified_date = datetime.datetime.now()
        return super(MyModel, self).save(*args, **kwargs)
于 2011-11-15T21:34:54.803 回答
27

顺便说一句,创建时间被标记到_id属性中 - 如果你这样做:

YourObject.id.generation_time

会给你一个日期时间戳。

于 2012-07-17T06:43:30.993 回答
6

一个不错的解决方案是为多个文档重用单个信号处理程序。

class User(Document):
    # other fields...
    created_at = DateTimeField(required=True, default=datetime.utcnow)
    updated_at = DateTimeField(required=True)

class Post(Document):
    # other fields...
    created_at = DateTimeField(required=True, default=datetime.utcnow)
    updated_at = DateTimeField(required=True)

def update_timestamp(sender, document, **kwargs):
    document.updated_at = datetime.utcnow()

signals.pre_save.connect(update_timestamp, sender=User)
signals.pre_save.connect(update_timestamp, sender=Post)

小心分配一个可调用而不是一个固定值作为默认值,例如 default=datetime.utcnow没有(). 此页面上的其他一些答案不正确,会导致created_at新文档始终设置为您的应用程序首次加载的时间。

datetime.utcnow在数据库中存储 UTC 日期(而不是)也总是更好datetime.now

于 2013-01-09T21:49:24.363 回答
4
# -*- coding: utf-8 -*-
from mongoengine import *
from mongoengine import signals
from datetime import datetime

class User(Document):
    email = StringField(required=True, unique=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)
    # audit fields
    created_on = DateTimeField(default=datetime.now())
    updated_on = DateTimeField(default=datetime.now())

    @classmethod
    def pre_save(cls, sender, document, **kwargs):
        document.updated_on = datetime.now()

signals.pre_save.connect(User.pre_save, sender=User)
于 2012-08-07T18:19:56.003 回答
4

如果您在一堆文档中使用时间戳字段,则可以通过创建抽象文档来保持代码干燥。

from datetime import datetime
from mongoengine import Document

class CreateUpdateDocument(Document):
    meta = {
        'abstract': True
    }

    # last updated timestamp
    updated_at = DateTimeField(default=datetime.now)

    # timestamp of when entry was created
    created_at = DateTimeField(default=datetime.now)

    def save(self, *args, **kwargs):
        if not self.created_at:
            self.created_at = datetime.now()
        self.updated_at = datetime.now()
        return super(CreateUpdateDocument, self).save(*args, **kwargs)
于 2014-10-02T11:17:41.613 回答
4

我首选的解决方案是使用@property装饰器返回从 ObjectId 中提取的创建日期时间:

@property
def creation_stamp(self):
    return self.id.generation_time
于 2014-11-07T14:49:01.750 回答
1

尝试使用 lambda 值:

import datetime
from mongoengine import Document

class MyModel(Document):
    creation_date = mongo.DateTimeField()
    modified_date = mongo.DateTimeField(default=lambda : datetime.datetime.now())
于 2020-04-23T11:22:11.177 回答
0

传统上,我将creation_date默认设置为datetime.now(),然后在管理表单上隐藏了该字段,这样您就可以消除用户覆盖正确值的可能性。这几乎不需要任何代码。

按照 Willian 的建议覆盖 save 方法也很有效,因为您可以通过编程方式阻止对 的任何更新creation_date并同时更新modfied_date

于 2011-11-18T17:34:15.103 回答
-8

您可以按照文档使用 auto_now_add 参数:

class MyModel(mongoengine.Document):
    creation_date = mongo.DateTimeField(auto_now_add = True)
    modified_date = mongo.DateTimeField(auto_now = True)
于 2011-11-18T15:12:36.187 回答