I am trying to add a creation_time
attribute to my documents. The following would be an example:
import datetime
class MyModel(mongoengine.Document):
creation_date = mongo.DateTimeField()
modified_date = mongo.DateTimeField(default=datetime.datetime.now)
Django models have built in parameter for their DateTimeField
objects like add_now
, etc.,
but MongoEngine does not support this.
I am wondering if best way to do this is the following:
m,created = MyModel.objects.get_or_create()
if created:
m.creation_date = datetime.datetime.now()
or if there is a better, nicer way.
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)
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.
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.
# -*- 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)
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
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())
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With