RuntimeWarning: DateTimeField menerima datetime yang naif

310

Saya mencoba mengirim surat sederhana menggunakan IPython. Saya belum menyiapkan model apa pun yang masih mengalami kesalahan ini. Apa yang bisa dilakukan?

Kesalahan: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/ init .py: 827: RuntimeWarning: DateTimeField menerima datetime naif (2013-09-04 14: 14: 13.698105) ketika dukungan zona waktu aktif. RuntimeWarning)

Mencoba: Langkah pertama adalah menambahkan USE_TZ = Trueke file pengaturan Anda dan menginstal pytz(jika mungkin).

Kesalahan berubah:

(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)
shifu
sumber

Jawaban:

490

Masalahnya bukan pada pengaturan Django, tetapi pada tanggal diteruskan ke model. Beginilah bentuk objek yang sadar zona waktu:

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

Dan inilah benda naif:

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

Jadi, jika Anda melewati tanggal email di mana saja (dan itu akhirnya sampai pada beberapa model), cukup gunakan Django now(). Jika tidak, maka itu mungkin masalah dengan paket yang ada yang mengambil tanggal tanpa zona waktu dan Anda dapat menambal paket, mengabaikan peringatan atau mengatur USE_TZ ke False.

kravietz
sumber
8
Di mana Anda menulis tzinfo=<UTC>, apa itu <UTC>? Itu bukan konstruksi sintaksis yang pernah saya lihat.
jameshfisher
4
Agak terlambat ke pesta, tetapi apa yang Anda lihat adalah output dari shell. Lebih khusus, itu adalah output dari metode repr objek datetime , yang mengembalikan informasi cetak objek
George Griffin
36
Di tempat-tempat di mana Anda menggunakan datetime.now, ubah timezone.now, dan tambahkan from django.utils import timezonedi bagian atas.
Unoti
12
Bagi mereka yang masih mencari bagian <UTC> itu, Anda dapat menggunakan ini:import pytz datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
Anoyz
Pengaturan saya USE_TZ = True, TIME_ZONE = 'UTC'. Tetapi ketika saya menggunakannya timezone.now()tidak menunjukkan tzinfo=<UTC>.... Jadi objek datetime ini dilewatkan sebagai naif. Mengapa itu terjadi?
user3595632
71

Gunakan fungsi django.utils.timezone.make_aware untuk membuat zona waktu objek naif Anda sadar dan menghindari peringatan tersebut.

Ini mengubah objek datetime naif (tanpa info zona waktu) ke objek yang memiliki info zona waktu (menggunakan zona waktu yang ditentukan dalam pengaturan Django Anda jika Anda tidak menentukannya secara eksplisit sebagai argumen kedua):

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
sumber
Terima kasih atas jawaban ini, ini adalah cara yang paling sesuai dengan django untuk mengubah tanggal yang naif menjadi tanggal dengan zona waktu pengaturan django saya :)
sodimel
Apakah mungkin untuk meletakkan ini di models.py?
Florent
@Florent tidak perlu mengubah apa pun dalam model jika Anda menggunakan utc timezone secara default, auto_nowdan auto_now_addakan berfungsi dengan baik untuk bidang datetime. Jika Anda perlu memiliki zona waktu sadar objek datetime saat ini dalam model untuk beberapa alasan - gunakan django.utils.timezone.now()fungsi.
dmrz
26

Hanya untuk memperbaiki kesalahan untuk mengatur waktu saat ini

from django.utils import timezone
import datetime

datetime.datetime.now(tz=timezone.utc) # you can use this value
Sachin G.
sumber
4
dan untuk datetime.datetime (9999, 01, 01, tzinfo = timezone.utc)
I. Yegor
IMO ini adalah solusi paling praktis
Ramtin
9

Seseorang dapat memperbaiki peringatan dan menggunakan zona waktu yang ditentukan dalam settings.py, yang mungkin berbeda dari UTC.

Sebagai contoh di settings.py saya saya punya:

USE_TZ = True
TIME_ZONE = 'Europe/Paris'

Ini solusinya; Keuntungannya adalah str(mydate)memberikan waktu yang tepat:

>>> 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'

Metode lain yang setara adalah menggunakan make_aware, lihat posting dmrz.

Edouard Thiel
sumber
3

Anda juga dapat mengesampingkan pengaturan, terutama berguna dalam pengujian:

from django.test import override_settings

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

Ini akan mencegah Anda dari melihat peringatan, pada saat yang sama segala sesuatu dalam kode Anda yang memerlukan waktu sadar zona waktu dapat memberi Anda masalah. Jika ini masalahnya, lihat jawaban kravietz.

radtek
sumber
2

Jika Anda mencoba mengubah datetime naif menjadi datetime dengan zona waktu di Django, berikut adalah solusi saya:

>>> 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 adalah datetime naif dan t2 adalah datetime dengan zona waktu di pengaturan Django.

hcf1425
sumber