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_nowauto_now_add 天生就使用datetime.now。将 TZ 感知设施插入 Django 似乎是 Django 的一个奇怪的遗漏,但却错过了这个非常重要的设施,但这两个 kwargs 的命运已经争论了很长时间。我的理由是它们被保留是为了向后兼容(并避免推回),但不要指望它们会得到任何爱。只需将default kwarg 设置为utcnow,不要担心auto_nowauto_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 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

django1.8 model : Field types

Django model中设置多个字段联合唯一约束

如何在 Django 中将 2 个模型字段结合在一起?

Django模型将字段与字段进行比较[重复]

如何在Django Db记录中设置多个字段

如何更新 django 模型实例的多个字段?