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)