EDITIERT:
Wie kann ich die Standardeinstellung eines Django-Felds auf eine Funktion festlegen, die jedes Mal ausgewertet wird, wenn ein neues Modellobjekt erstellt wird?
Ich möchte Folgendes tun, außer dass in diesem Code der Code einmal ausgewertet wird und der Standard für jedes erstellte Modellobjekt auf das gleiche Datum festgelegt wird, anstatt den Code jedes Mal auszuwerten, wenn ein Modellobjekt erstellt wird:
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
ORIGINAL:
Ich möchte einen Standardwert für einen Funktionsparameter erstellen, der dynamisch ist und bei jedem Aufruf der Funktion aufgerufen und festgelegt wird. Wie kann ich das machen? z.B,
from datetime import datetime
def mydate(date=datetime.now()):
print date
mydate()
mydate() # prints the same thing as the previous call; but I want it to be a newer value
Insbesondere möchte ich es in Django tun, z.
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
django
django-models
parameters
lambda
default
Rob Bednark
quelle
quelle
Antworten:
Die Frage ist falsch. Wenn Sie ein Modellfeld in Django erstellen, definieren Sie keine Funktion, daher sind die Standardwerte für Funktionen irrelevant:
Diese letzte Zeile definiert keine Funktion. Es wird eine Funktion aufgerufen, um ein Feld in der Klasse zu erstellen.
PRE Django 1.7
Mit Django können Sie ein Callable als Standard übergeben und es wird jedes Mal aufgerufen, genau wie Sie möchten:
Django 1.7+
Bitte beachten Sie, dass seit Django 1.7 die Verwendung von Lambda als Standardwert nicht empfohlen wird (siehe Kommentar @stvnw). Der richtige Weg, dies zu tun, besteht darin, eine Funktion vor dem Feld zu deklarieren und sie als aufrufbar in default_value mit dem Namen arg zu verwenden:
Weitere Informationen finden Sie in der Antwort von @simanas unten
quelle
get_default_my_date
?Das zu tun
default=datetime.now()+timedelta(days=1)
ist absolut falsch!Es wird ausgewertet, wenn Sie Ihre Instanz von Django starten. Wenn Sie unter Apache sind, wird es wahrscheinlich funktionieren, da Apache bei einigen Konfigurationen Ihre Django-Anwendung bei jeder Anfrage widerruft. Trotzdem können Sie eines Tages Ihren Code durchsehen und herausfinden, warum dies nicht wie erwartet berechnet wird .
Der richtige Weg, dies zu tun, besteht darin, ein aufrufbares Objekt an das Standardargument zu übergeben. Dies kann eine datetime.today-Funktion oder eine benutzerdefinierte Funktion sein. Dann wird es jedes Mal ausgewertet, wenn Sie einen neuen Standardwert anfordern.
quelle
get_deadline(my_parameter)
?deadline
Feld wieder und löschst gleichzeitig dieget_deadline
Funktion? Ich habe ein Feld mit einer Funktion für einen Standardwert entfernt, aber jetzt stürzt Django beim Start ab, nachdem die Funktion entfernt wurde. Ich könnte die Migration manuell bearbeiten, was in diesem Fall in Ordnung wäre, aber was wäre, wenn Sie einfach die Standardfunktion ändern und die alte Funktion entfernen möchten?Es gibt einen wichtigen Unterschied zwischen den folgenden beiden DateTimeField-Konstruktoren:
Wenn Sie
auto_now_add=True
im Konstruktor verwenden, ist die von my_date referenzierte Datums- und Uhrzeitangabe "unveränderlich" (nur einmal festgelegt, wenn die Zeile in die Tabelle eingefügt wird).Mit
auto_now=True
wird der Datum / Uhrzeit-Wert jedoch jedes Mal aktualisiert, wenn das Objekt gespeichert wird.Dies war definitiv ein Problem für mich an einem Punkt. Als Referenz finden Sie die Dokumente hier:
https://docs.djangoproject.com/de/dev/ref/models/fields/#datetimefield
quelle
Manchmal müssen Sie nach dem Erstellen eines neuen Benutzermodells möglicherweise auf Modelldaten zugreifen.
So generiere ich ein Token für jedes neue Benutzerprofil mit den ersten 4 Zeichen seines Benutzernamens:
quelle
Das kann man nicht direkt machen; Der Standardwert wird ausgewertet, wenn die Funktionsdefinition ausgewertet wird. Es gibt jedoch zwei Möglichkeiten.
Zuerst können Sie jedes Mal eine neue Funktion erstellen (und dann aufrufen).
Oder verwenden Sie einfach einen speziellen Wert, um die Standardeinstellung zu markieren. Beispielsweise:
Wenn
None
es sich um einen absolut vernünftigen Parameterwert handelt und es keinen anderen vernünftigen Wert gibt, den Sie an seiner Stelle verwenden könnten, können Sie einfach einen neuen Wert erstellen, der definitiv außerhalb des Bereichs Ihrer Funktion liegt:In einigen seltenen Fällen schreiben Sie Metacode, der wirklich absolut alles aufnehmen muss, auch nicht
mydate.func_defaults[0]
. In diesem Fall müssen Sie Folgendes tun:quelle
myfunc
Funktion darin besteht, a zu nehmen (und zu drucken)datetime
; Sie haben es geändert, damit es nicht so verwendet werden kann.Übergeben Sie die Funktion als Parameter, anstatt das Ergebnis des Funktionsaufrufs zu übergeben.
Das heißt, stattdessen:
Versuche dies:
quelle
print datetime.now()
bedingungslos keine Parameter übernehmen .datetime.now
Funktion. Jeder Benutzer, der einen nicht standardmäßigen Wert übergibt, übergibt jedoch eine Datums- und Uhrzeitangabe, keine Funktion.foo = datetime.now(); myfunc(foo)
wird erhöhenTypeError: 'datetime.datetime' object is not callable
. Wenn ich Ihre Funktion tatsächlich nutzen wollte, müsste ichmyfunc(lambda: foo)
stattdessen so etwas tun , was keine vernünftige Schnittstelle ist.