django 时区如何与 model.field 的 auto_now_add 一起使用
Posted
技术标签:
【中文标题】django 时区如何与 model.field 的 auto_now_add 一起使用【英文标题】:How django time zone works with model.field's auto_now_add 【发布时间】:2012-07-01 01:07:11 【问题描述】:我想 Django 1.4 中添加了时区管理,所以这个问题是相当新的。
我使用了一个简单的模型
class Sample(models.Model):
...
date_generated = models.DateTimeField(auto_now_add = True)
当我尝试检索新创建的记录时,它失败了。
min_datetime = datetime.now() - timedelta(seconds = 300)
sample = Sample.objects.get(date_generated__gte = min_datetime)
服务器发出警告。
DateTimeField received a naive DateTime (2012-06-29 15:02:15.074000) while time zone support is active.
我想出了两个解决这个问题的办法。
在settings.py中禁用时区管理
USE_TZ = False
但这并不总是可取的。 2.改变
date_generated = models.DateTimeField(auto_now_add = True)
到
date_generated = models.DateTimeField(default=datetime.now())
是保持时区管理正常工作的解决方案
【问题讨论】:
【参考方案1】:使用 django 的时区工具
from django.utils import timezone
date_generated = models.DateTimeField(default=timezone.now)
【讨论】:
对于查看此线程的其他人:请注意答案是now
而不是 now()
。第二个会在加载服务器时进行评估,这不是您想要的。【参考方案2】:
问题出在你的头上:datetime.now()
不知道 TZ,所以你是一个在天真的 TZ 中喂养的人。请参阅Django docs on this issue。设置default=datetime.now
时它起作用的原因是您将值强制为天真的日期时间,因此当您稍后将其与另一个天真的日期时间进行比较时,没有问题。
您需要通过以下方式获得“现在”:
import datetime
from django.utils.timezone import utc
now = datetime.datetime.utcnow().replace(tzinfo=utc)
【讨论】:
这是否意味着我不能只使用 auto_now 或 auto_now_add 如果我有 USE_TZ = True? 似乎auto_now
和auto_now_add
天生就使用datetime.now
。将 TZ 感知设施插入 Django 似乎是 Django 的一个奇怪的遗漏,但却错过了这个非常重要的设施,但这两个 kwargs 的命运已经争论了很长时间。我的理由是它们被保留是为了向后兼容(并避免推回),但不要指望它们会得到任何爱。只需将default
kwarg 设置为utcnow
,不要担心auto_now
或auto_now_add
,如果你想知道TZ 的日期时间。
谢谢克里斯。我不认为“默认”可以代替“auto_now”,因为后者总是更新每次保存的时间,而“默认”仅在字段没有值时。
获得“现在”的更快方法...from django.utils.timezone import now as utcnow
。然后now = utcnow()
会给你和@ChrisPratt 一样的结果。
django 1.4.5 显示 auto_now 或 auto_now_add 使用 timezone.now() ,而不是 datetime.now() 所以使用它们是安全的。【参考方案3】:
小心设置DateTimeField
默认值datetime.now()
,因为这将在 Apache/nginx 加载 Django(或启动开发服务器时)计算单个值,并且所有后续记录都将收到该值。
因此,请始终使用auto_now_add
。
【讨论】:
只使用default=datetime.now
,不带括号。【参考方案4】:
在您的 Django 模型中:
从settings.py
导入 TIME_ZONE
date_field = models.DateTimeField(default=datetime.now(pytz.timezone(TIME_ZONE)))
【讨论】:
这将在 django 加载时计算并且不再更新以上是关于django 时区如何与 model.field 的 auto_now_add 一起使用的主要内容,如果未能解决你的问题,请参考以下文章