RuntimeWarning: DateTimeField получил наивное datetime

311

Я пытаюсь отправить простую почту, используя IPython. Я не настроил ни одной модели, все еще получающей эту ошибку. Что может быть сделано?

Ошибка: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/ init .py: 827: RuntimeWarning: DateTimeField получил наивное datetime (2013-09-04 14: 14: 13.698105) при активной поддержке часового пояса. RuntimeWarning)

Попробовал: первый шаг - добавить USE_TZ = Trueв файл настроек и установить pytz(если это возможно).

Ошибка изменена:

(learn)sourabh@sL:~/Django/learn/event$ python manage.py shell
/home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py:53: RuntimeWarning: SQLite received a naive datetime (2013-09-05 00:59:32.181872) while time zone support is active.
  RuntimeWarning)
Шифу
источник

Ответы:

490

Проблема не в настройках Django, а в дате, переданной модели. Вот как выглядит объект с учетом часового пояса:

>>> from django.utils import timezone
>>> import pytz
>>> timezone.now()
datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)

А вот и наивный объект:

>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2013, 11, 20, 20, 9, 26, 423063)

Так что, если вы передаете дату электронной почты где-либо (и она в конечном итоге попадает в какую-то модель), просто используйте Django now(). Если нет, то это, вероятно, проблема с существующим пакетом, который выбирает дату без часового пояса, и вы можете исправить пакет, проигнорировать предупреждение или установить для USE_TZ значение False.

kravietz
источник
8
Куда пишешь tzinfo=<UTC>, что есть <UTC>? Это не синтаксическая конструкция, которую я видел.
jameshfisher
4
Немного опоздал на вечеринку, но вы видите вывод из оболочки. Более конкретно, это результат метода repr объекта datetime , который возвращает информацию об объекте для печати.
Джордж Гриффин
36
В местах, где вы использовали datetime.now, измените его на timezone.nowи добавьте from django.utils import timezoneсверху.
Unoti
12
Для тех, кто все еще ищет эту часть <UTC>, вы можете использовать это:import pytz datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
Anoyz
Мои настройки USE_TZ = True, TIME_ZONE = 'UTC'. Но когда я использую timezone.now()его, он не отображается tzinfo=<UTC>.... Так что этот объект даты и времени передается как наивный. Почему это происходит?
user3595632
72

Используйте функцию django.utils.timezone.make_aware, чтобы ваши наивные объекты даты и времени знали часовой пояс и избегали этих предупреждений.

Он преобразует наивный объект datetime (без информации о часовом поясе) в объект с информацией о часовом поясе (используя часовой пояс, указанный в настройках django, если вы явно не указали его в качестве второго аргумента):

import datetime
from django.conf import settings
from django.utils.timezone import make_aware

naive_datetime = datetime.datetime.now()
naive_datetime.tzinfo  # None

settings.TIME_ZONE  # 'UTC'
aware_datetime = make_aware(naive_datetime)
aware_datetime.tzinfo  # <UTC>
dmrz
источник
Спасибо за этот ответ, это самый совместимый с django способ преобразовать наивные даты в даты с
часовым
Можно ли поместить это в models.py?
Флорент
@Florent: нет необходимости что-либо менять в моделях, если вы по умолчанию используете часовой пояс utc, auto_nowи auto_now_addон отлично подойдет для полей даты и времени. Если вам по какой-то причине необходимо знать текущую дату и время в моделях в часовом поясе - используйте django.utils.timezone.now()функцию.
дмрз
26

Просто чтобы исправить ошибку, чтобы установить текущее время

from django.utils import timezone
import datetime

datetime.datetime.now(tz=timezone.utc) # you can use this value
Сачин Г.
источник
4
и для datetime.datetime (9999, 01, 01, tzinfo = timezone.utc)
И. Егор
ИМО это самое практичное решение
Рамтин
9

Можно как исправить предупреждение, так и использовать часовой пояс, указанный в settings.py, который может отличаться от UTC.

Например в моем settings.py у меня есть:

USE_TZ = True
TIME_ZONE = 'Europe/Paris'

Вот решение; преимущество в том, что str(mydate)дает правильное время:

>>> from datetime import datetime
>>> from django.utils.timezone import get_current_timezone
>>> mydate = datetime.now(tz=get_current_timezone())
>>> mydate
datetime.datetime(2019, 3, 10, 11, 16, 9, 184106, 
    tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
>>> str(mydate)
'2019-03-10 11:16:09.184106+01:00'

Другой эквивалентный метод использует make_aware, см. Сообщение dmrz.

Эдуард Тиль
источник
5

Быстро и грязно - выключите его:

USE_TZ = False

в твоем settings.py

gies0r
источник
1
Когда USE_TZ имеет значение True и база данных поддерживает часовые пояса (например, PostgreSQL), установка этого параметра является ошибкой docs.djangoproject.com/en/2.2/ref/settings/#time-zone
Marcaum54
3

Вы также можете переопределить настройки, особенно полезные в тестах:

from django.test import override_settings

with override_settings(USE_TZ=False):
    # Insert your code that causes the warning here
    pass

Это помешает вам увидеть предупреждение, в то же время все, что в вашем коде требует указание даты и времени в часовом поясе, может вызвать проблемы. Если это так, смотрите ответ Кравец.

radtek
источник
2

Если вы пытаетесь преобразовать наивную дату и время в часовой пояс в django, вот мое решение:

>>> import datetime
>>> from django.utils import timezone
>>> t1 = datetime.datetime.strptime("2019-07-16 22:24:00", "%Y-%m-%d %H:%M:%S")
>>> t1
    datetime.datetime(2019, 7, 16, 22, 24)
>>> current_tz = timezone.get_current_timezone()
>>> t2 = current_tz.localize(t1)
>>> t2
    datetime.datetime(2019, 7, 16, 22, 24, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
>>>

t1 - наивное время даты, а t2 - дата и время с часовым поясом в настройках django.

hcf1425
источник