Domyślne opcje Django DateField

82

Mam model z polem daty i godziny:

date = models.DateField(_("Date"), default=datetime.now())

Kiedy sprawdzam aplikację we wbudowanym panelu administracyjnym django, DateFielddołączony jest również czas, więc jeśli spróbujesz ją zapisać, zwracany jest błąd. Jak ustawić domyślną tylko datę? (też datetime.today()nie działa)

damon
źródło

Odpowiedzi:

150

Dlatego należy zawsze importować podstawowy datetimemoduł:import datetime zamiast w datetimeklasie w ramach tego modułu: from datetime import datetime.

Innym błędem, który popełniłeś, jest faktyczne wywołanie funkcji domyślnie, z rozszerzeniem (). Oznacza to, że wszystkie modele otrzymają datę w momencie pierwszego zdefiniowania klasy - więc jeśli serwer będzie działał przez kilka dni lub tygodni bez ponownego uruchamiania Apache, wszystkie elementy otrzymają tę samą datę początkową.

Więc pole powinno być:

import datetime
date = models.DateField(_("Date"), default=datetime.date.today)
Daniel Roseman
źródło
Czy można to zrobić, dodając deltę czasu? Na przykład: default = datetime.date.today + datetime.timedelta (days = 4) ... ten kod nie działa, ale taka jest idea. (To prawda, metoda zapisu to jedno miejsce, w którym można to zrobić, ale zastanawiam się, czy istnieje sposób, aby to zrobić jako część definicji)
Joe J
1
@Joe J: to naprawdę powinno być nowe pytanie. Ale fakt, że możesz użyć wywoływalnego, oznacza, że ​​możesz po prostu zdefiniować własną funkcję, która zwraca dzisiaj + 4.
Daniel Roseman,
23
Co _("Date")robisz?
benregn,
10
@benregn Nadaje polu etykietę „Data”, ale oznacza je do tłumaczenia przy użyciu systemu internacjonalizacji.
Daniel Roseman,
Dzięki za wyjaśnienie, właśnie zacząłem tworzyć Django i było dla mnie trochę niejasne, czy robi coś więcej niż tylko etykietowanie.
benregn
38

Twoim błędem jest użycie datetimemodułu zamiast datemodułu. Miałeś zamiar to zrobić:

from datetime import date
date = models.DateField(_("Date"), default=date.today)

Jeśli chcesz uchwycić tylko aktualną datę, właściwym sposobem na to jest użycie auto_now_addparametru:

date = models.DateField(_("Date"), auto_now_add=True)

Jednak dokumentacja modelfield wyraźnie to stwierdza auto_now_addi zawszeauto_now będzie używać bieżącej daty i nie jest wartością domyślną, którą można zastąpić.

Eric Palakovich Carr
źródło
8
date = models.DateTimeField(default=datetime.now, blank=True)
andyshi
źródło
5
DateTimeField to nie to samo. Jeśli podasz datę i godzinę jako domyślną DateField, będziesz mieć problemy.
onekiloparsec
6

Myślę, że lepszym sposobem rozwiązania tego problemu byłoby użycie wywoływanej daty i godziny:

from datetime import datetime

date = models.DateField(default=datetime.now)

Zwróć uwagę, że nie użyto nawiasów. Jeśli użyłeś nawiasów, wywołałbyś now()funkcję tylko raz (podczas tworzenia modelu). Zamiast tego przekazujesz wywoływalny argument jako argument, który jest wywoływany za każdym razem, gdy tworzona jest instancja modelu.

Podziękowania dla Django Musings . Użyłem go i działa dobrze.

ppicom
źródło
4

To powinno załatwić sprawę:

models.DateTimeField(_("Date"), auto_now_add = True)
btk
źródło
1
mój przyjacielu, myślę, że źle to przeczytałeś. Pytanie dotyczy DateField, a nie DateTimeField.
xxbinxx
2

Możesz również użyć lambda. Przydatne, jeśli używasz django.utils.timezone.now

date = models.DateField(_("Date"), default=lambda: now().date())
Neil
źródło
6
Spójrz na dokumentację . Nie jest dobrze używać lambdy jako domyślnego opakowania wywoływanego: Note that lambdas cannot be used for field options like default because they cannot be serialized by migrations. See that documentation for other caveats.
pulina
@pulina masz rację, ale w tym przypadku, gdy potrzebujesz daty powiązanej ze skonfigurowaną
strefą
Nie. Możesz wskazać rzeczywistą funkcję w kodzie. Dowolna funkcja lub odniesienie do metody zgodnie z tym w połączeniu, które jest funkcją najwyższego poziomu modelu.
pulina