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

问题: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

I have the below db model:

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)

I add a new instance by using the below:

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

My issue: all records in database have the same value in date field, which is the date of the first payment. After the server restarts, one record has the new date and the other records have the same as the first. It looks as if some data is cached, but I can’t find where.

database: 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的模型字段参考中提供了更多信息。

it looks like datetime.now() is being evaluated when the model is defined, and not each time you add a record.

Django has a feature to accomplish what you are trying to do already:

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

or

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

The difference between the second example and what you currently have is the lack of parentheses. By passing datetime.now without the parentheses, you are passing the actual function, which will be called each time a record is added. If you pass it datetime.now(), then you are just evaluating the function and passing it the return value.

More information is available at Django’s model field reference


回答 1

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

参考:

所以去这样的事情:

from django.utils.timezone import now


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

Instead of using datetime.now you should be really using from django.utils.timezone import now

Reference:

so go for something like this:

from django.utils.timezone import now


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

回答 2

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

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

因此,以下应该起作用:

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

From the documentation on the django model default field:

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

Therefore following should work:

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。

David had the right answer. The parenthesis () makes it so that the callable timezone.now() is called every time the model is evaluated. If you remove the () from timezone.now() (or datetime.now(), if using the naive datetime object) to make it just this:

default=timezone.now

Then it will work as you expect:
New objects will receive the current date when they are created, but the date won’t be overridden every time you do manage.py makemigrations/migrate.

I just encountered this. Much thanks to David.


回答 4

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

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

date = models.DateTimeField(auto_now_add=True)

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

The datetime.now() is evaluated when the class is created, not when new record is being added to the database.

To achieve what you want define this field as:

date = models.DateTimeField(auto_now_add=True)

This way the date field will be set to current date for each new record.


回答 5

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

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

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

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

read_only = 'date'

同样,我这样做是因为我的默认值通常是不可编辑的,除非另有说明,否则管理页面会忽略不可编辑的内容。但是,设置默认值和实现关键的auto_add之间肯定有区别。测试一下!

The answer to this one is actually wrong.

Auto filling in the value (auto_now/auto_now_add isn’t the same as default). The default value will actually be what the user sees if its a brand new object. What I typically do is:

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

Make sure, if your trying to represent this in an Admin page, that you list it as ‘read_only’ and reference the field name

read_only = 'date'

Again, I do this since my default value isn’t typically editable, and Admin pages ignore non-editables unless specified otherwise. There is certainly a difference however between setting a default value and implementing the auto_add which is key here. Test it out!


回答 6

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

datetime.now() is being evaluated once, when your class is instantiated. Try removing the parenthesis so that the function datetime.now is returned and THEN evaluated. I had the same issue with setting default values for my DateTimeFields and wrote up my solution here.


回答 7

从Python语言参考中的“ 函数定义”下

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

幸运的是,如果您将auto_now参数用作,则Django可以执行您想要的操作DateTimeField

date = models.DateTimeField(auto_now=True)

请参阅Django文档中的DateTimeField

From the Python language reference, under Function definitions:

Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that that same “pre-computed” value is used for each call.

Fortunately, Django has a way to do what you want, if you use the auto_now argument for the DateTimeField:

date = models.DateTimeField(auto_now=True)

See the Django docs for DateTimeField.


回答 8

在Django 3.0中 auto_now_add似乎可以使用auto_now

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

In Django 3.0 auto_now_add seems to work with auto_now

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