2012-06-29 13 views
18

Przypuszczam, że zarządzanie strefą czasową zostało dodane do django 1.4, więc problem jest całkiem nowy.Jak działa strefa czasowa django z auto_now_add model.field

użyłem prostego modelu

class Sample(models.Model): 
    ... 
    date_generated = models.DateTimeField(auto_now_add = True) 

Kiedy próbuję pobrać nowo utworzonego rekordu jej się nie powiedzie.

min_datetime = datetime.now() - timedelta(seconds = 300) 
sample = Sample.objects.get(date_generated__gte = min_datetime) 

i serwer wydaje ostrzeżenie.

DateTimeField received a naive datetime (2012-06-29 15:02:15.074000) while time zone support is active. 

Wymyśliłem dwa rozwiązania tego problemu.

  1. Wyłącz zarządzanie strefa czasowa w settings.py

    USE_TZ = False 
    

    ale nie zawsze jest to desierable.

  2. zmieniając

    date_generated = models.DateTimeField(auto_now_add = True) 
    

    do

    date_generated = models.DateTimeField(default=datetime.now()) 
    

    jest rozwiązanie, które utrzymuje zarządzania strefą czasową pracę

Odpowiedz

17

Problem polega na koniec: datetime.now() nie jest TZ świadomy, więc jesteś tym, który karmi się naiwną TZ. Zobacz Django docs on this issue. Powodem jego działania podczas ustawiania default=datetime.now jest wymuszenie wartości na naiwnej datetime, więc gdy porównasz ją później z inną naiwną datetime, nie ma problemu.

Musisz dostać się „teraz” w następujący sposób:

import datetime 
from django.utils.timezone import utc 

now = datetime.datetime.utcnow().replace(tzinfo=utc) 
+6

Czy to znaczy, że nie można po prostu użyć auto_now lub auto_now_add jeśli mam USE_TZ = true? – dannyroa

+5

Wygląda na to, że 'auto_now' i' auto_now_add' z natury używają 'datetime.now'. Wydaje się dziwnym zaniedbaniem dla Django wstawiania urządzeń obsługujących TZ do Django, ale tęsknię za tym bardzo ważnym, ale los tych dwóch kwargów był długo dyskutowany. Moje rozumowanie polega na tym, że są one pozostawione dla kompatybilności wstecznej (i aby uniknąć odpychania), ale nie oczekuj, że dostaną jakąkolwiek miłość. Po prostu ustaw 'default' kwarg na' utcnow' i nie przejmuj się 'auto_now' lub' auto_now_add', jeśli chcesz mieć TZ w pamięci. –

+0

Dzięki Chris. Nie sądzę, aby "default" działał w zastępstwie "auto_now", ponieważ ten ostatni zawsze aktualizuje czas dla każdego zapisu, podczas gdy "default" jest tylko wtedy, gdy pole nie ma wartości. – dannyroa

7

być ostrożnym ustawienie wartości DateTimeField domyślnej datetime.now(), jako że będzie obliczyć pojedynczą wartość, gdy Apache/nginx ładunki Django (lub po uruchomieniu serwer programistyczny), a wszystkie kolejne rekordy otrzymają tę wartość.

Zawsze należy stosować auto_now_add z tego powodu.

+13

Po prostu użyj 'default = datetime.now' bez nawiasów. –

13
utils

Zastosowanie strefa czasowa Django

from django.utils import timezone 
date_generated = models.DateTimeField(default=timezone.now) 
+1

Dla innych oglądających ten wątek: zauważ, jak odpowiedź brzmi "teraz" a nie "teraz()". Drugi oceni podczas ładowania serwera, co nie jest tym, czego potrzebujesz. – Pieter

Powiązane problemy