我正在将我的项目从 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/型号.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
有什么区别,为什么它们在这些情况下会导致警告/错误?
在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
可以在需要时重新计算值。
不同之处在于timezone.now
是在运行时执行的可调用对象,而timezone.now()
返回该函数的输出。
对于models.DateTimeField
,您需要使用可调用对象。更好的是,只需设置auto_now_add
为您执行此操作:
datetime_released = models.DateTimeField(auto_now_add=True)
另一方面,过滤器不接受可调用对象 - 它需要一个值。因此,在将其作为参数传递给筛选器时,必须计算timezone.now()
。
self.filter(date_available__lte = timezone.now())
您希望根据当前时间对数据库进行查询。所以你需要它以字符串格式。
在datetime_released = models.DateTimeField(default=timezone.now)
中,您希望默认值为当前时间。所以你不能在那里有一个字符串。相反,您提供了一个可以返回当前时间的函数。
now() 在加载模型时执行,并在加载时返回日期时间对象/时间字符串。(因此是姜戈警告!(模型文件(如果在服务器启动时完全执行)
now将传递 now 方法,并且仅在类/模型实例化时执行,在正确的时间创建时间戳(正确的方式,以及大多数人试图实现的目标)。
在筛选器示例中,仅在调用筛选器函数时调用它。如果您不执行 (now()) 并将馈送该方法,并且永远不会生成所需的 DateTime 对象。(错误,期望一个字符串,得到,其他东西)
timezone.now() 在加载模型时返回当前时间戳。另一方面,timezone.now 作为参数传递给函数,并在创建对象时调用它(在类实例化时)
在下面的代码中
def date_available(self):
return self.filter(date_available__lte = timezone.now())
函数date_availabe需要一个函数字符串,以便在返回 self.filter 时解析为函数。