Django:timezone.now vs timezone.now()

时间:2016-07-07 04:55:11

标签: python django timezone

我正在将我的项目从Django 1.8.2升级到1.9.7,我收到了这个警告:

[Run V6.0 In Window 7]

这是my_app / models.py中的行:

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

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

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

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

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

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

在这里,如果删除括号,则会抛出错误:

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

我可以通过根据需要添加/删除括号来获得这两个工作,但TypeError: expected string or buffertimezone.now()之间的区别是什么?为什么它们会在这些情况下导致警告/错误?< / p>

5 个答案:

答案 0 :(得分:21)

在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收到callable时,每次请求默认值时都会调用callable。

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

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

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

答案 1 :(得分:10)

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

对于models.DateTimeField,您需要使用callable。更好的是,只需设置为您执行此操作的auto_now_add

datetime_released = models.DateTimeField(auto_now_add=True)

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

答案 2 :(得分:1)

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

现在将传递now方法,并且只有在实例化类/模型时才会执行,在正确的时间创建时间戳(正确的方式,以及大多数人想要实现的)。

在过滤器示例中,仅在调用过滤器函数时调用它。 如果你没有执行(now())并将提供方法,并且永远不会生成所需的datetime对象。 (错误,期望一个字符串,得到,别的东西)

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

在以下代码中

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

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