Ich habe das folgende DB-Modell:
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)
Ich füge eine neue Instanz hinzu, indem ich Folgendes verwende:
tp = TermPayment.objects.create(**kwargs)
Mein Problem: Alle Datensätze in der Datenbank haben den gleichen Wert im Datumsfeld, dem Datum der ersten Zahlung. Nach dem Neustart des Servers hat ein Datensatz das neue Datum und die anderen Datensätze das gleiche wie der erste. Es sieht so aus, als ob einige Daten zwischengespeichert sind, aber ich kann nicht finden, wo.
Datenbank: MySQL 5.1.25
django v1.1.1
default=datetime.now
- Hinweis, ohne Aufruf wie innow()
Nicht der Standard für DateTimeField, aber ... auf jeden Fall praktisch.Antworten:
Es sieht so aus,
datetime.now()
als würde es ausgewertet, wenn das Modell definiert wird, und nicht jedes Mal, wenn Sie einen Datensatz hinzufügen.Django hat eine Funktion, mit der Sie das erreichen können, was Sie bereits versuchen:
oder
Der Unterschied zwischen dem zweiten Beispiel und dem, was Sie derzeit haben, ist das Fehlen von Klammern. Wenn Sie
datetime.now
ohne Klammern übergeben, übergeben Sie die eigentliche Funktion, die jedes Mal aufgerufen wird, wenn ein Datensatz hinzugefügt wird. Wenn Sie es übergebendatetime.now()
, bewerten Sie nur die Funktion und übergeben ihr den Rückgabewert.Weitere Informationen sind unter Djangos verfügbar Modellfeld Referenz
quelle
expiry = models.DateTimeField(default=datetime.now + timedelta(days=30))
def now_plus_30(): return datetime.now() + timedelta(days = 30)
, und dannmodels.DateTimeField(default=now_plus_30)
default=lambda: datetime.now()+timedelta(days=30)
Anstatt zu verwenden
datetime.now
, sollten Sie wirklich verwendenfrom django.utils.timezone import now
Referenz:
django.utils.timezone.now
Also mach so etwas:
quelle
auto_now_add
(was zeitzonenabhängig ist), können Sie aufgrund schwerwiegender Zeitzonenunterschiede falsche Berechnungen erhalten.Aus der Dokumentation zum Standardfeld des Django-Modells:
Der Standardwert für das Feld. Dies kann ein Wert oder ein aufrufbares Objekt sein. Wenn aufrufbar, wird es jedes Mal aufgerufen, wenn ein neues Objekt erstellt wird.
Daher sollte Folgendes funktionieren:
quelle
default
( django-chinese-docs-14.readthedocs.io/en/latest/ref/models/… )David hatte die richtige Antwort. Die Klammer () bewirkt, dass die aufrufbare Zeitzone.now () jedes Mal aufgerufen wird, wenn das Modell ausgewertet wird. Wenn Sie () aus timezone.now () (oder datetime.now () entfernen, wenn Sie das naive datetime-Objekt verwenden), um genau dies zu erreichen:
Dann funktioniert es wie erwartet:
Neue Objekte erhalten das aktuelle Datum, wenn sie erstellt werden, aber das Datum wird nicht jedes Mal überschrieben, wenn Sie verwalten.py makemigrations / migrate ausführen.
Ich bin gerade darauf gestoßen. Vielen Dank an David.
quelle
Das
datetime.now()
wird beim Erstellen der Klasse ausgewertet, nicht beim Hinzufügen eines neuen Datensatzes zur Datenbank.Um das zu erreichen, was Sie wollen, definieren Sie dieses Feld als:
Auf diese Weise wird das
date
Feld für jeden neuen Datensatz auf das aktuelle Datum gesetzt.quelle
Die Antwort auf diese Frage ist tatsächlich falsch.
Automatisches Ausfüllen des Werts (auto_now / auto_now_add ist nicht dasselbe wie Standard). Der Standardwert ist tatsächlich das, was der Benutzer sieht, wenn es sich um ein brandneues Objekt handelt. Was ich normalerweise mache, ist:
Stellen Sie sicher, dass Sie, wenn Sie versuchen, dies auf einer Admin-Seite darzustellen, diese als "read_only" auflisten und auf den Feldnamen verweisen
Ich mache dies erneut, da mein Standardwert normalerweise nicht bearbeitet werden kann und Admin-Seiten nicht bearbeitbare Elemente ignorieren, sofern nicht anders angegeben. Es gibt jedoch sicherlich einen Unterschied zwischen dem Festlegen eines Standardwerts und dem Implementieren von auto_add, was hier der Schlüssel ist. Probieren Sie es aus!
quelle
datetime.now()
wird einmal ausgewertet, wenn Ihre Klasse instanziiert wird. Entfernen Sie die Klammern, damit die Funktiondatetime.now
zurückgegeben und dann ausgewertet wird. Ich hatte das gleiche Problem beim Festlegen von Standardwerten für meinDateTimeField
s und schrieb meine Lösung hier auf .quelle
Aus der Python-Sprachreferenz unter Funktionsdefinitionen :
Glücklicherweise hat Django eine Möglichkeit, das zu tun, was Sie wollen, wenn Sie das
auto_now
Argument für Folgendes verwendenDateTimeField
:Weitere Informationen zu DateTimeField finden Sie in den Django-Dokumenten .
quelle
In Django 3.0
auto_now_add
scheint das zu funktionierenauto_now
reg_date=models.DateField(auto_now=True,blank=True)
quelle