python django orm mongodb mongoengine

orm python mongodb



Atributo mongoengine creation_time en el documento (8)

Estoy tratando de agregar un atributo creation_time a mis documentos. El siguiente sería un ejemplo:

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

Los modelos de Django han incorporado un parámetro para sus objetos DateTimeField como add_now , etc., pero MongoEngine no admite esto.

Me pregunto si la mejor manera de hacer esto es la siguiente:

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

O si hay una forma mejor, más bonita.


Además, el tiempo de creación se estampa en el atributo _id , si lo hace:

YourObject.id.generation_time

Te daré un sello de fecha y hora.


Mi solución preferida es usar el decorador @property para devolver la fecha y hora de creación extraída del ObjectId:

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


Podría usar el parámetro auto_now_add según la documentation :

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


Podrías anular el método de guardado.

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)


Si está utilizando el campo de marca de tiempo en un grupo de Documentos, puede mantener su código DRY creando un Documento abstracto en su lugar.

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)


Tradicionalmente, he establecido el valor predeterminado de creation_date en datetime.now() y luego he ocultado el campo en el formulario de administración para eliminar la posibilidad de que un usuario sobrescriba el valor correcto. Eso requiere casi ningún código.

La anulación del método de guardado sugerido por Willian también es efectiva, ya que puede bloquear de manera programática cualquier actualización a la fecha de creation_date y actualizar la fecha de modfied_date al mismo tiempo.


Una buena solución es reutilizar un controlador de señal único para varios documentos.

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)

Tenga cuidado de asignar un valor que se pueda llamar y no un valor fijo como predeterminado, por ejemplo, default=datetime.utcnow sin () . Algunas de las otras respuestas en esta página son incorrectas y harían que created_at para documentos nuevos siempre se establezca en el momento en que se cargó la aplicación por primera vez.

También siempre es mejor almacenar las fechas UTC ( datetime.utcnow lugar de datetime.now ) en su base de datos.


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