Атрибут времени создания Mongoengine в документе

Я пытаюсь добавить creation_time атрибут для Моих документов. Следующий пример:

import datetime

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

модели Django имеют встроенный параметр для их DateTimeField объекты типа add_now, etc., но MongoEngine не поддерживает это.

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

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

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

8 ответов


вы можете переопределить метод save.

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)

в стороне, время создания штампуется в


# -*- 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)

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

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) в базе данных.


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

@property
def creation_stamp(self):
    return self.id.generation_time

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

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)

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

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


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

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