Django datetime问题(default=datetime.now())

我有下面的db模型:

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

430418 次浏览

看起来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的模型字段参考中找到

django模型默认字段中的文档:

字段的默认值。这可以是一个值或一个可调用对象。如果是可调用的,则每次创建新对象时都会调用它。

因此,以下几点应该起作用:

date = models.DateTimeField(default=datetime.now,blank=True)

datetime.now()在创建类时计算,而不是在向数据库添加新记录时计算。

为了达到你想要的效果,将这个字段定义为:

date = models.DateTimeField(auto_now_add=True)

这样,date字段将被设置为每个新记录的当前日期。

来自Python语言引用,在函数定义下:

在执行函数定义时计算默认参数值。这意味着在定义函数时,表达式只计算一次,并且每次调用都使用相同的“预计算”值。

幸运的是,Django有一种方法可以做你想做的事情,如果你对DateTimeField使用auto_now参数:

date = models.DateTimeField(auto_now=True)

关于DateTimeField,请参阅Django文档。

当你的类被实例化时,datetime.now()只被求值一次。尝试删除圆括号,以便返回函数datetime.now,然后求值。我在为我的__abc2设置默认值时遇到了同样的问题,并写下了我的解决方案在这里

这个问题的答案其实是错误的。

自动填充值(auto_now/auto_now_add与默认值不同)。默认值实际上是用户看到的,如果它是一个全新的对象。我通常做的是:

date = models.DateTimeField(default=datetime.now, editable=False,)

请确保,如果您试图在管理页面中表示这一点,您将其列为“read_only”并引用字段名称

read_only = 'date'

同样,我这样做是因为我的默认值通常是不可编辑的,而且Admin页面会忽略不可编辑的内容,除非另有指定。当然,设置默认值和实现auto_add之间是有区别的,这是这里的关键。测试一下吧!

大卫的答案是正确的。括号()使得可调用的 timezone.now()在每次计算模型时都被调用。如果你从timezone.now()(或datetime.now(),如果使用天真的datetime对象)中删除(),使其变成这样:

default=timezone.now

那么它将像你期望的那样工作:
新对象在创建时将接收当前日期,但不会在每次执行manage.py makemig/ migrate.

我刚刚遇到了这个。非常感谢大卫。

你应该真正使用from django.utils.timezone import now而不是datetime.now

参考:

所以你可以这样做:

from django.utils.timezone import now




created_date = models.DateTimeField(default=now, editable=False)

在Django 3.0中,auto_now_add似乎与auto_now一起工作

reg_date=models.DateField(auto_now=True,blank=True)

如果你只需要DateField,试试这个

date = models.DateField(auto_now=False, auto_now_add=False, null=True, blank=True)

如果你需要日期和时间,试试这个

date = models.DateTimeField(auto_now_add=True, null=True, blank=True)