已编辑:
如何将Django字段的默认值设置为每次创建新模型对象时都要求值的函数?
我想做一些类似于下面的事情,除了在这段代码中,代码只计算一次,并为每个创建的模型对象设置默认值,而不是每次创建模型对象时都计算代码:
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_datetime = models.DateTimeField(default=datetime.now() + timedelta(days=1))
ORIGINAL:
我想为一个函数参数创建一个默认值,这样它是动态的,每次调用函数时都会被调用和设置。我该怎么做?例如,在一个实施例中,
from datetime import datetime
def mydatetime(date=datetime.now()):
print date
mydatetime()
mydatetime() # prints the same thing as the previous call; but I want it to be a newer value
具体来说,我想在Django中实现,例如,
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_datetime = models.DateTimeField(default=datetime.now() + timedelta(days=1))
7条答案
按热度按时间tpgth1q71#
这个问题被误导了。在Django中创建模型字段时,你没有定义函数,所以函数的默认值是无关紧要的:
最后一行不是定义函数;它调用一个函数来在类中创建一个字段。
在这种情况下,
datetime.now() + timedelta(days=1)
将被计算一次,并存储为默认值。PRE Django 1.7
Django [允许你传递一个可调用函数作为默认值][1],每次它都会调用它,就像你想要的那样:
Django 1.7+
请注意,自Django 1.7以来,不建议使用lambda作为默认值(参见:@stvnw comment)。正确的方法是在字段之前声明一个函数,并将其用作default_value中的一个名为arg的可调用函数:
更多信息请参见下面的@simanas答案[1]:https://docs.djangoproject.com/en/dev/ref/models/fields/#default
xpszyzbs2#
这样做
default=datetime.now()+timedelta(days=1)
是绝对错误的!当你启动你的django示例时,它会被评估。如果你在apache下,它可能会工作,因为在某些配置下,apache会在每个请求上撤销你的django应用程序,但你仍然会发现你自己有一天在查看你的代码,并试图找出为什么这不是你期望的计算结果。
正确的方法是将一个可调用对象传递给默认参数。它可以是datetime.today函数或您的自定义函数。然后,每当您请求新的默认值时,它都会进行评估。
fnvucqvd3#
下面两个DateTimeField构造函数之间有一个重要的区别:
如果在构造函数中使用
auto_now_add=True
,则my_date引用的日期时间是“不可变的”(仅在将行插入表时设置一次)。但是,对于
auto_now=True
,每次保存对象时都会更新datetime值。这对我来说绝对是一个陷阱。作为参考,文档在这里:
https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield
ujv3wf0j4#
有时,您可能需要在创建新用户模型后访问模型数据。
下面是我如何使用用户名的前4个字符为每个新用户配置文件生成令牌:
f4t66c6m5#
你不能直接这么做当函数定义被求值时,缺省值被求值。但有两种方法可以绕过它。
首先,每次都可以创建(然后调用)一个新函数。
或者,更简单地说,只是使用一个特殊的值来标记默认值。例如:
如果
None
是一个完全合理的参数值,并且没有其他合理的值可以使用它,则可以创建一个新值,该值肯定在函数的域之外:在一些罕见的情况下,您编写的元代码确实需要能够接受任何东西,甚至是
mydate.func_defaults[0]
。在这种情况下,你必须这样做:nfzehxib6#
将函数作为参数传入,而不是传入函数调用的结果。
也就是说,而不是这样:
试试这个:
kcwpcxri7#
您应该设置
get_my_datetime
而不设置()
,它将返回当前日期和时间(+1天)到DateTimeField()作为默认值,如下所示。* 不要用()
设置get_my_datetime()
,因为默认的日期和时间是Django服务器启动时(未更改),你应该使用Django的timezone.now(),因为Python的datetime.now()在TIME_ZONE = 'UTC'时不能正确地将UTC保存在数据库中,这是settings.py
的默认值:在你的代码中,不要设置
datetime.now() + timedelta(days=1)
,因为默认的日期和时间是Django服务器启动的时候(未更改):