DateTimeField received a naive datetime
引言:最近在做django的一些小东西的时候,某个数据表里面有类型为DateTimeField的字段,导入时间的时候报错:RuntimeWarning: DateTimeField Artical.create_time received a naive datetime.
起因
开始还以为仅仅是一个警告,就想直接放过....不过我还是好好的看了一下,结果一查数据库发现插入到数据库的时间与当前时间不相同。
我一开始用的是datetime.datetime.today()
输出的时间和当前时间一致但是它给出了一个警告,我当时寻思也没啥问题呀,时间也对,但是好奇心驱使下还是去百度了一下。
发现问题
百度了之后,阅读了某不知名网友的博客,了解到了,django
中有一些时间读取与存储不一致的问题。
具体是这样的:在django1.4
以后,存在两个概念:naive time 与 active time。简单点讲,naive time就是不带时区的时间,相关Active time就是带时区的时间。举例来说,使用datetime.datetime.utcnow()、datetime.datetime.now()
输出的类似2015-05-11 09:10:33.080451就是不带时区的时间(naive time),而使用django.util.timezone.now()
输出的类似2015-05-11 09:05:19.936835+00:00的时间就是带时区的时间(Active time),其中+00:00表示的就是时区相对性。
原因:
Django在1.4版本之后存储如果设置了USE_TZ=True
,则存储到数据库中的时间永远是UTC时间。这时如果settings
里面设置了USE_TZ=True
与TIME_ZONE = 'UTC'
,用datetime.datetime.now()
获取的时间django
会把这个时间当成UTC时间存储到数据库中去,这也就导致了其将当前时间转换成了UTC时间(也就是加了八个小时),而读的时候直接按UTC时间读出来,这就是网上很多人遇到的存储到数据库中的时间比本地时间会快8个小时的原因。
解决问题
了解了这些知识后,解决起问题就简单了只是仅仅了解为什么而已,接下来就是解决方案。
晓得了上文说的时区问题,那么最简单的方法就是去setting里面修改设置就行了,我这边修改设置为USE_TZ=True
与TIME_ZONE = 'Asia/Shanghai'
,用datetime.datetime.now()
获取的时间,其获取的时间与本地就一致了。
然后我这边遇到了一个奇葩问题...多次提交得到的时间相同???
好了这个问题是我自己的离谱操作导致的..我把数据库时间字段默认值设为了
datetime.now()
..导致后面插入时候数据都是同一个。(这边提醒大家不要这样做...)
时间是改正了,但是它还是报错,那是因为你这边是没事了,因为设定了是默认为TIME_ZONE = 'Asia/Shanghai'
,但是你远方在南洋的大表哥如何用你这个系统时候他插入数据库的时间就会出现偏差。
为了防止出现这样的错误,我们还是用django默认的输出时间的函数---timezone.now()
换成timezone.now()
后警告就消失了。timezone.now()
是如果setting
中配置USE_TZ=True
则输出的是UTC时间(naive time),如果setting
中配置USE_TZ=False
,则该输出时间是不带时区的.
下面是两个设置下时间输出的对比: 1.True:
2.False:
结尾:
好了到这一步应该没有啥问题了,那么最后完结撒花。