Django:timezone.now 与 timezone.now()

Posted

技术标签:

【中文标题】Django:timezone.now 与 timezone.now()【英文标题】:Django: timezone.now vs timezone.now() 【发布时间】:2016-11-09 07:37:51 【问题描述】:

我正在将我的项目从 Django 1.8.2 升级到 1.9.7,我收到以下警告:

WARNINGS:
my_app.my_model.date_available: (fields.W161) Fixed default value provided.
HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. 
If you want to have the current date as default, use `django.utils.timezone.now

这是来自 my_app/models.py 的行:

from django.utils import timezone
...
class my_model(models.Model):
    ...
    datetime_released = models.DateTimeField(default=timezone.now() )

如果我删除括号并改为使用:

datetime_released = models.DateTimeField(default=timezone.now )

Django 警告消失了。两者有什么区别?


在我项目的另一个领域,我在查询集过滤器中使用 timezone.now():

def date_available(self):
        return self.filter(date_available__lte = timezone.now())

这里,如果我去掉括号,就会抛出错误:

TypeError: expected string or buffer


我可以通过根据需要添加/删除括号来完成这两项工作,但是timezone.now()timezone.now 之间有什么区别,为什么它们在这些情况下会导致警告/错误?

【问题讨论】:

type(now()) 重新运行一个日期时间对象。 type(now) 现在重新运行方法 【参考方案1】:

在 python 中,一切都是对象,包括函数。这意味着您可以将函数影响到变量:

>>> from django.utils import timezone
>>> foo = timezone.now
>>> foo
<function django.utils.timezone.now>
>>> foo()
datetime.datetime(2016, 7, 7, 9, 11, 6, 489063)

函数是一个可调用对象:

>>> callable(foo)
True
>>> callable(foo())
False

default 接收到一个可调用对象时,每次请求一个默认值时都会调用该可调用对象。

另一方面,当您在设置default 之前调用timezone.now() 时,会给出并固定该值。提醒一下,以下行仅在服务器启动时执行一次,因为它是一个类属性:

    datetime_released = models.DateTimeField(default=timezone.now())

因此timezone.now() 只执行一次。传递可调用的timezone.now 可以在需要时重新计算值。

【讨论】:

【参考方案2】:

不同之处在于timezone.now 是在运行时执行的可调用对象,而timezone.now() 返回该函数的输出。

对于models.DateTimeField,您需要使用可调用对象。更好的是,只需设置 auto_now_add 即可:

datetime_released = models.DateTimeField(auto_now_add=True)

另一方面,过滤器不接受可调用对象 - 它需要一个值。因此,在将其作为参数传递给过滤器时,您必须评估 timezone.now()

【讨论】:

这里值得一提的是,当你传递timezone.now() 时,你实际上是在 django 启动时传递了该函数的输出(这是它被评估的时候),而当你传递了timezone.now 你传递的是由 django 懒惰评估的函数对象。 如果你想要一个有创建时间戳的模型怎么办?在这种情况下,timezone.now() 会比 timezone.now 更好吗?timezone.now 最终会经常被重新评估?【参考方案3】:

self.filter(date_available__lte = timezone.now()) 中,您想根据当前时间查询数据库。所以你需要它的字符串格式。

datetime_released = models.DateTimeField(default=timezone.now) 中,您希望默认为当前时间。所以你不能在那里有一个字符串。相反,您提供了一个可以返回当前时间的函数。

【讨论】:

【参考方案4】:

now() 在模型加载时执行,并在加载时返回一个日期时间对象/时间字符串。 (因此是 Django 警告!) (模型文件如果在服务器启动时完全执行)

now 将传递 now 方法,并且仅在类/模型被实例化时才会执行,在正确的时间创建时间戳(正确的方法,以及大多数人试图实现的目标)。

在过滤器示例中,它仅在调用过滤器函数时才被调用。 如果您不执行 (now()) 并将提供该方法,并且永远不会生成所需的日期时间对象。 (错误,需要一个字符串,得到,别的)

【讨论】:

【参考方案5】:

timezone.now() 返回模型加载时的当前时间戳。另一方面,timezone.now 作为参数传递给函数,并在创建对象时调用(在类实例化时)

在下面的代码中

def date_available(self):
    return self.filter(date_available__lte = timezone.now())

函数 date_availabe 在返回 self.filter 时需要一个函数字符串来解析为函数

【讨论】:

以上是关于Django:timezone.now 与 timezone.now()的主要内容,如果未能解决你的问题,请参考以下文章

如何格式化 django timezone.now()

[转] datetime.nowdatetime.utcnow以及Django中的timezone.now之间的区别

python 使用Django单位中的自定义日期模拟/替换timezone.now()

django.utils.timezone返回天真的约会?

Django 查询集注释与日期时间计算

django数据库