web-dev-qa-db-fra.com

Django problèmes de datetime (default = datetime.now ())

J'ai le modèle ci-dessous:

from datetime import datetime    

class TermPayment(models.Model):
    # I have excluded fields that are irrelevant to the question
    date = models.DateTimeField(default=datetime.now(), blank=True)

J'ajoute une nouvelle instance en utilisant ce qui suit:

tp = TermPayment.objects.create(**kwargs)

Mon problème: tous les enregistrements de la base de données ont la même valeur dans le champ de date, qui correspond à la date du premier paiement. Après le redémarrage du serveur, un enregistrement a la nouvelle date et les autres ont la même chose que le premier. Il semble que certaines données soient mises en cache, mais je ne trouve pas où.

base de données: mysql 5.1.25

Django v1.1.1

245
Shamanu4

il semble que datetime.now() soit en cours d'évaluation lors de la définition du modèle, et non à chaque fois que vous ajoutez un enregistrement.

Django a une fonctionnalité pour accomplir ce que vous essayez déjà de faire:

date = models.DateTimeField(auto_now_add=True, blank=True)

ou

date = models.DateTimeField(default=datetime.now, blank=True)

La différence entre le deuxième exemple et ce que vous avez actuellement est le manque de parenthèses. En passant datetime.now sans les parenthèses, vous transmettez la fonction réelle, qui sera appelée chaque fois qu'un enregistrement est ajouté. Si vous passez datetime.now(), vous évaluez simplement la fonction et lui transmettez la valeur de retour.

Plus d'informations sont disponibles chez Django référence du champ de modèle

532
Carson Myers

Au lieu d'utiliser _datetime.now_, vous devriez vraiment utiliser _from Django.utils.timezone import now_

Référence:

alors optez pour quelque chose comme ceci:

_from Django.utils.timezone import now


created_date = models.DateTimeField(default=now, editable=False)
_
86
andilabs

À partir de la documentation sur le champ par défaut du modèle Django:

La valeur par défaut du champ. Cela peut être une valeur ou un objet appelable. Si appelable, il sera appelé chaque fois qu'un nouvel objet est créé.

Par conséquent, les actions suivantes devraient fonctionner:

date = models.DateTimeField(default=datetime.now,blank=True)
26
mykhal

David avait la bonne réponse. La parenthèse () fait en sorte que le appelable timezone.now () soit appelé chaque fois que le modèle est évalué. Si vous supprimez le () de timezone.now () (ou datetime.now (), si vous utilisez l'objet naïf datetime), procédez comme suit:

default=timezone.now

Ensuite, cela fonctionnera comme prévu:
Les nouveaux objets recevront la date du jour de leur création, mais cette date ne sera pas remplacée à chaque fois que vous gérerez.py makemigrations/migrate.

Je viens de rencontrer ceci. Merci beaucoup à David.

16
MicahT

La datetime.now() est évaluée lors de la création de la classe et non lors de l'ajout d'un nouvel enregistrement à la base de données.

Pour atteindre ce que vous voulez définir ce champ comme:

date = models.DateTimeField(auto_now_add=True)

De cette façon, le champ date sera défini sur la date du jour pour chaque nouvel enregistrement.

9
Bartosz

datetime.now() est évalué une fois, lorsque votre classe est instanciée. Essayez de supprimer les parenthèses afin que la fonction datetime.now soit renvoyée et ALORS évaluée. J'ai eu le même problème avec la définition des valeurs par défaut pour mon DateTimeFields et écrit ma solution ici .

6
David

La réponse à cette question est en fait fausse.

La saisie automatique de la valeur (auto_now/auto_now_add n'est pas identique à la valeur par défaut). La valeur par défaut sera en réalité ce que l'utilisateur verra s'il s'agit d'un nouvel objet. Ce que je fais généralement est:

date = models.DateTimeField(default=datetime.now, editable=False,)

Assurez-vous, si vous essayez de représenter ceci dans une page d'administration, que vous le listiez avec 'read_only' et référenciez le nom du champ.

read_only = 'date'

Encore une fois, je le fais car ma valeur par défaut n’est généralement pas modifiable, et les pages d’administrateur ignorent les éléments non modifiables, sauf indication contraire. Cependant, il y a certainement une différence entre définir une valeur par défaut et implémenter auto_add, qui est la clé ici. Testez-le!

6
Andrew Harris

Dans la référence du langage Python, sous Définitions de fonctions :

Les valeurs de paramètre par défaut sont évaluées lorsque la définition de la fonction est exécutée. Cela signifie que l'expression est évaluée une fois, lorsque la fonction est définie, et que la même valeur "pré-calculée" est utilisée pour chaque appel.

Heureusement, Django a le moyen de faire ce que vous voulez, si vous utilisez l'argument auto_now pour la DateTimeField:

date = models.DateTimeField(auto_now=True)

Voir la documentation Django pour DateTimeField .

5
ars