问题:Django datetime问题(default = datetime.now())
我有下面的数据库模型:
from datetime import datetime
class TermPayment(models.Model):
# I have excluded fields that are irrelevant to the question
date = models.DateTimeField(default=datetime.now(), blank=True)
我使用以下方法添加新实例:
tp = TermPayment.objects.create(**kwargs)
我的问题:数据库中的所有记录在date字段中都具有相同的值,这是第一次付款的日期。服务器重新启动后,一个记录具有新的日期,其他记录与第一个相同。看起来好像有些数据被缓存了,但是我找不到位置。
数据库:mysql 5.1.25
Django v1.1.1
回答 0
似乎datetime.now()
是在定义模型时(而不是每次添加记录时)正在评估。
Django具有一项功能,可以完成您正在尝试做的事情:
date = models.DateTimeField(auto_now_add=True, blank=True)
要么
date = models.DateTimeField(default=datetime.now, blank=True)
第二个示例与当前示例之间的区别在于缺少括号。通过datetime.now
不带括号的传递,就传递了实际的函数,每次添加记录时都会调用该函数。如果传递它datetime.now()
,那么您只是在评估函数并将其返回值传递给它。
Django的模型字段参考中提供了更多信息。
回答 1
而不是使用datetime.now
您应该真正使用from django.utils.timezone import now
参考:
所以去这样的事情:
from django.utils.timezone import now
created_date = models.DateTimeField(default=now, editable=False)
回答 2
从django模型默认字段的文档中:
字段的默认值。这可以是值或可调用对象。如果可以调用,则每次创建新对象时都会调用它。
因此,以下应该起作用:
date = models.DateTimeField(default=datetime.now,blank=True)
回答 3
大卫的回答正确。括号()使得每次评估模型时都调用可调用的 timezone.now()。如果从timezone.now()(如果使用朴素的datetime对象,则从datezone.now()或datetime.now())中删除()来做到这一点:
default=timezone.now
然后它将按您期望的那样工作:
新对象在创建时会收到当前日期,但是每次您进行manage.py makemigrations / migrate时都不会覆盖该日期。
我刚遇到这个。非常感谢David。
回答 4
在datetime.now()
创建类时评估,而不是在将新记录添加到数据库时评估。
要实现您想要的目标,请将该字段定义为:
date = models.DateTimeField(auto_now_add=True)
这样,该date
字段将被设置为每个新记录的当前日期。
回答 5
这个问题的答案实际上是错误的。
自动填写值(auto_now / auto_now_add与默认值不同)。默认值实际上是用户看到的全新对象。我通常要做的是:
date = models.DateTimeField(default=datetime.now, editable=False,)
确保,如果您试图在“管理”页面中表示此信息,请确保将其列为“ read_only”并引用字段名称
read_only = 'date'
同样,我这样做是因为我的默认值通常是不可编辑的,除非另有说明,否则管理页面会忽略不可编辑的内容。但是,设置默认值和实现关键的auto_add之间肯定有区别。测试一下!
回答 6
datetime.now()
在实例化您的类时被评估一次。尝试删除括号,以便datetime.now
返回函数并评估THEN。我在为设置默认值时遇到了同样的问题,DateTimeField
并在此处写下了解决方案。
回答 7
从Python语言参考中的“ 函数定义”下:
执行功能定义时,将评估默认参数值。这意味着在定义函数时,表达式将被计算一次,并且每次调用都使用相同的“预先计算”值。
幸运的是,如果您将auto_now
参数用作,则Django可以执行您想要的操作DateTimeField
:
date = models.DateTimeField(auto_now=True)
请参阅Django文档中的DateTimeField。
回答 8
在Django 3.0中 auto_now_add
似乎可以使用auto_now
reg_date=models.DateField(auto_now=True,blank=True)