Mongoengine creation_time -attribuut in document

Ik probeer een attribuut create_time toe te voegen aan mijn documenten. Het volgende zou een voorbeeld zijn:

import datetime

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

Django-modellen hebben een ingebouwde parameter voor hun DateTimeField -objecten zoals add_now , enz., maar MongoEngine ondersteunt dit niet.

Ik vraag me af of de beste manier om dit te doen het volgende is:

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

of als er een betere, mooiere manier is.

24

8 antwoord

U kunt de opslagmethode overschrijven.

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)
51
toegevoegd
override clean methode in plaats van save zou beter moeten zijn, documenten hier
toegevoegd de auteur xialu, de bron
@ Brenden1995 Nee, het werkt niet met update.
toegevoegd de auteur Willian, de bron
Dit is precies wat ik nodig had. Ik had het standaardbit uitgezocht, maar het negeren van de opslagmethode om de gewijzigde tijd te volgen, is perfect. Dank je :)
toegevoegd de auteur Dawson, de bron
Het probleem hiermee is echter dat de opslagfunctie niet wordt aangeroepen als u een update uitvoert in plaats van een .save toch?
toegevoegd de auteur Nazariy1995, de bron

Even terzijde, de creatietijd wordt gestempeld in het attribuut _id - als je dat doet:

YourObject.id.generation_time

Geeft je een datetime-stempel.

18
toegevoegd
Dit is beter dan het geaccepteerde antwoord. Ik heb @property gebruikt in een functie als deze om de created_time te maken: def created_at (self): return self.id.generation_time als self.id else None
toegevoegd de auteur aaaronic, de bron
Precies wat ik zocht, bedankt.
toegevoegd de auteur Viktor Stískala, de bron

U kunt de parameter auto_now_add gebruiken volgens documentatie :

class MyModel(mongoengine.Document):
    creation_date = mongo.DateTimeField(auto_now_add = True)
    modified_date = mongo.DateTimeField(auto_now = True)
7
toegevoegd
deze parameters werken niet in Mongoengine
toegevoegd de auteur josephmisiti, de bron
Dat is het meest ongelukkig. Het juiste antwoord is dan het overschrijven van de opslag zoals in het geaccepteerde antwoord. Ik zou een patch maken om de functie toe te voegen :)
toegevoegd de auteur Laur Ivan, de bron
Wil je het een beetje uitleggen?
toegevoegd de auteur Laur Ivan, de bron
Dit is geen Django-kerel ...
toegevoegd de auteur Ron Reiter, de bron

Een leuke oplossing is het hergebruiken van één signaalhandler voor meerdere documenten.

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)

Zorg ervoor dat u een opvraagbare en niet een vaste waarde toewijst als de standaardwaarde, bijvoorbeeld default = datum/tijd zonder () . Sommige van de andere antwoorden op deze pagina zijn niet correct en veroorzaken created_at omdat nieuwe documenten altijd moeten worden ingesteld op het moment dat uw app voor het eerst werd geladen.

Het is ook altijd beter om UTC-datums ( datetime.utcnow in plaats van datetime.now ) in uw database op te slaan.

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

Mijn geprefereerde oplossing is om de decormaker @property te gebruiken om de creatie van de datetime terug te halen uit het ObjectId:

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

Als u het tijdstempelveld in een aantal documenten gebruikt, kunt u uw code behouden DRY door in plaats hiervan een abstract document te maken.

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)
2
toegevoegd
U kunt self.updated_at = datetime.now() onder een else -instructie zetten, zodat u het idee kunt houden van "als de updated_at geen is, betekent dit dat de model is nooit bijgewerkt ".
toegevoegd de auteur ldavid, de bron

Traditioneel heb ik de creation_date standaard ingesteld op datetime.now() en vervolgens het veld op het beheerdersformulier verborgen, zodat je de mogelijkheid kunt verwijderen dat een gebruiker de juiste waarde overschrijft waarde. Dat vereist bijna geen code.

Het negeren van de opslagmethode zoals voorgesteld door Willian is ook effectief, omdat u programmeerbaar elke update naar de creation_date kunt blokkeren en tegelijkertijd de modfied_date kunt bijwerken.

0
toegevoegd
als je 'traditioneel' zegt, bedoel je dan met name de Django ORM of MongoEngine?
toegevoegd de auteur josephmisiti, de bron