[Django]-Mongoengine creation_time attribute in Document

75πŸ‘

βœ…

You could override the save method.

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)
πŸ‘€Willian

28πŸ‘

As an aside, the creation time is stamped into the _id attribute – if you do:

YourObject.id.generation_time

Will give you a datetime stamp.

πŸ‘€Ben Hughes

6πŸ‘

One nice solution is reusing a single signal handler for multiple documents.

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)

Be careful to assign a callable and not a fixed-value as the default, for example default=datetime.utcnow without (). Some of the other answers on this page are incorrect and would cause created_at for new documents to always be set to the time your app was first loaded.

It’s also always better to store UTC dates (datetime.utcnow instead of datetime.now) in your database.

πŸ‘€codebutler

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)
πŸ‘€allisson

4πŸ‘

If you are using the timestamp field in a bunch of Documents you can keep your code DRY by creating an abstract Document instead.

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)
πŸ‘€Vikas Gulati

4πŸ‘

My preferred solution is to use the @property decorator to return the creation datetime as extracted from the ObjectId:

@property
def creation_stamp(self):
    return self.id.generation_time
πŸ‘€Emanuel Ey

1πŸ‘

Try use lambda value:

import datetime
from mongoengine import Document

class MyModel(Document):
    creation_date = mongo.DateTimeField()
    modified_date = mongo.DateTimeField(default=lambda : datetime.datetime.now())
πŸ‘€JohnDHH

0πŸ‘

Traditionally, I’ve set the creation_date default to datetime.now() and then have hidden the field on the admin form so you remove the possibility of a user overwriting the correct value. That requires almost no code.

Overriding the save method as suggested by Willian is also effective since you can programmtically block any updates to the creation_date and update the modfied_date at the same time.

-8πŸ‘

You could use auto_now_add parameter as per documentation:

class MyModel(mongoengine.Document):
    creation_date = mongo.DateTimeField(auto_now_add = True)
    modified_date = mongo.DateTimeField(auto_now = True)
πŸ‘€Laur Ivan

Leave a comment