Mongoengine creation_time атрибут в документе - PullRequest
26 голосов
/ 11 ноября 2011

Я пытаюсь добавить атрибут 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 не поддерживает это.

IМне интересно, если лучший способ сделать это заключается в следующем:

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

или есть лучший, более хороший способ.

Ответы [ 8 ]

56 голосов
/ 16 ноября 2011

Вы можете переопределить метод сохранения.

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)
21 голосов
/ 17 июля 2012

Кроме того, время создания указывается в атрибуте _id - если вы делаете:

YourObject.id.generation_time

Даст вам отметку даты и времени.

4 голосов
/ 10 января 2013

Хорошим решением является повторное использование одного обработчика сигналов для нескольких документов.

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 во время первой загрузки приложения.

Всегда лучше хранить даты в формате UTC (datetime.utcnowвместо datetime.now) в вашей базе данных.

4 голосов
/ 07 августа 2012
# -*- 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)
3 голосов
/ 07 ноября 2014

Мое предпочтительное решение - использовать декоратор @property для возврата даты и времени создания, извлеченной из ObjectId:

@property
def creation_stamp(self):
    return self.id.generation_time
3 голосов
/ 02 октября 2014

Если вы используете поле метки времени в пачке Документов, вы можете сохранить свой код DRY , создав вместо этого абстрактный документ.

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)
0 голосов
/ 18 ноября 2011

Традиционно я установил creation_date по умолчанию datetime.now(), а затем скрыл поле в форме администратора, чтобы вы исключили возможность перезаписи пользователем правильного значения.Это почти не требует кода.

Переопределение метода сохранения, предложенного Виллианом, также эффективно, поскольку вы можете программно блокировать любые обновления creation_date и обновлять modfied_date одновременно.

0 голосов
/ 18 ноября 2011

Вы можете использовать параметр auto_now_add согласно документации :

class MyModel(mongoengine.Document):
    creation_date = mongo.DateTimeField(auto_now_add = True)
    modified_date = mongo.DateTimeField(auto_now = True)
...