首页 文章

Django日期时间问题(默认= datetime.now())

提问于
浏览 771
222

我有这样的db模型:

from datetime import datetime    

class TermPayment(models.Model):
    # cut out some fields, non relevant to the question
    date = models.DateTimeField(default=datetime.now(), blank=True)

当添加新实例时:

tp = TermPayment.objects.create(**kwargs)

我有一个问题:数据库中的所有记录在日期字段中具有相同的值 - 第一次付款的日期 . 服务器重启后 - 一条记录有新日期,其他记录与第一条记录相同 . 它看起来像是使用了一些数据缓存,但我无法找到它 .

数据库:mysql 5.1.25

django v1.1.1

8 回答

  • 487

    从Python语言参考,在Function definitions下:

    执行函数定义时,将评估默认参数值 . 这意味着在定义函数时,表达式被计算一次,并且每个调用使用相同的“预先计算”值 .

    幸运的是,如果对 DateTimeField 使用 auto_now 参数,Django有办法做你想做的事:

    date = models.DateTimeField(auto_now=True)
    

    有关DateTimeField的信息,请参阅Django文档 .

  • 68

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

    default=timezone.now
    

    然后它将按预期工作:
    新对象将在创建时收到当前日期,但每次执行manage.py makemigrations / migrate时都不会覆盖日期 .

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

  • 23

    来自django模型默认字段的documentation

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

    因此,以下应该工作:

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

    这个问题的答案实际上是错误的 .

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

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

    如果您尝试在管理员页面中表示此内容,请确保将其列为“read_only”并引用字段名称

    read_only = 'date'
    

    同样,我这样做是因为我的默认值通常不可编辑,管理页面会忽略不可编辑的内容,除非另有说明 . 然而,在设置默认值和实现auto_add之间肯定存在差异,这是关键 . 测试出来!

  • 9

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

    参考:

  • 6

    在定义模型时,似乎正在评估 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的model field reference

  • 6

    当您的类被实例化时, datetime.now() 被评估一次 . 尝试删除括号,以便返回函数 datetime.now 并进行THEN计算 . 我在为 DateTimeField 设置默认值时遇到了同样的问题,并写了我的解决方案here .

  • 5

    在创建类时评估 datetime.now() ,而不是在将新记录添加到数据库时评估 .

    要实现您想要的目标,请将此字段定义为:

    date = models.DateTimeField(auto_now_add=True)
    

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

相关问题