Django auto_now 和 auto_now_add
对于 Django 1.1。
我的 models.py 中有这个:
class User(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
当更新一行时,我得到:
[Sun Nov 15 02:18:12 2009] [error] /home/ptarjan/projects/twitter-meme/django/db/backends/mysql/base.py:84: Warning: Column 'created' cannot be null
[Sun Nov 15 02:18:12 2009] [error] return self.cursor.execute(query, args)
我的数据库的相关部分是:
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
这是值得关注的原因吗?
附带问题:在我的管理工具中,这两个字段没有显示。这是预期的吗?
For Django 1.1.
I have this in my models.py:
class User(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
When updating a row I get:
[Sun Nov 15 02:18:12 2009] [error] /home/ptarjan/projects/twitter-meme/django/db/backends/mysql/base.py:84: Warning: Column 'created' cannot be null
[Sun Nov 15 02:18:12 2009] [error] return self.cursor.execute(query, args)
The relevant part of my database is:
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
Is this cause for concern?
Side question: in my admin tool, those two fields aren't showing up. Is that expected?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
任何带有
auto_now 的字段
属性集也将继承editable=False
,因此不会显示在管理面板中。过去有人讨论过制作auto_now
和auto_now_add
参数消失了,尽管它们仍然存在,但我觉得你最好只使用 自定义save()
方法。因此,为了使其正常工作,我建议不要使用
auto_now
或auto_now_add
而是定义您自己的save()
方法以确保created
仅在未设置id
时更新(例如首次创建项目时),并在每次项目时更新modified
已保存。我对使用 Django 编写的其他项目做了完全相同的事情,因此您的
save()
看起来像这样:编辑以响应评论:
原因我只是坚持重载
save()
与依赖这些字段参数有两个方面:django.utils.timezone.now()
与datetime.datetime.now()
,因为它将返回 TZ-aware 或 naivedatetime.datetime
对象取决于settings.USE_TZ
。为了解决OP看到错误的原因,我不太清楚,但看起来
created
根本没有被填充,尽管有auto_now_add=True
。对我来说,它是一个错误,并在上面的小列表中强调了第 1 项:auto_now
和auto_now_add
充其量是不稳定的。Any field with the
auto_now
attribute set will also inheriteditable=False
and therefore will not show up in the admin panel. There has been talk in the past about making theauto_now
andauto_now_add
arguments go away, and although they still exist, I feel you're better off just using a customsave()
method.So, to make this work properly, I would recommend not using
auto_now
orauto_now_add
and instead define your ownsave()
method to make sure thatcreated
is only updated ifid
is not set (such as when the item is first created), and have it updatemodified
every time the item is saved.I have done the exact same thing with other projects I have written using Django, and so your
save()
would look like this:Edit in response to comments:
The reason why I just stick with overloading
save()
vs. relying on these field arguments is two-fold:django.utils.timezone.now()
vs.datetime.datetime.now()
, because it will return a TZ-aware or naivedatetime.datetime
object depending onsettings.USE_TZ
.To address why the OP saw the error, I don't know exactly, but it looks like
created
isn't even being populated at all, despite havingauto_now_add=True
. To me it stands out as a bug, and underscores item #1 in my little list above:auto_now
andauto_now_add
are flaky at best.但我想指出,接受的答案中表达的观点有些过时了。根据最近的讨论(django bug #7634 和 #12785),
auto_now
和auto_now_add
不会去任何地方,即使你去了在原始讨论中,您会发现强烈反对自定义保存方法中的 RY(如 DRY)。已经提供了更好的解决方案(自定义字段类型),但没有获得足够的动力将其纳入 django。您可以用三行编写自己的代码(Jacob Kaplan-Moss'建议)。
But I wanted to point out that the opinion expressed in the accepted answer is somewhat outdated. According to more recent discussions (django bugs #7634 and #12785),
auto_now
andauto_now_add
are not going anywhere, and even if you go to the original discussion, you'll find strong arguments against the RY (as in DRY) in custom save methods.A better solution has been offered (custom field types), but didn't gain enough momentum to make it into django. You can write your own in three lines (it's Jacob Kaplan-Moss' suggestion).
谈论一个附带问题:如果您想在管理中查看此字段(尽管您无法编辑它),您可以将
readonly_fields
添加到您的管理类中。嗯,这仅适用于最新的 Django 版本(我相信是 1.3 及更高版本)
Talking about a side question: if you want to see this fields in admin (though, you won't be able to edit it), you can add
readonly_fields
to your admin class.Well, this applies only to latest Django versions (I believe, 1.3 and above)
我认为这里最简单(也许也是最优雅)的解决方案是利用您可以将
default
设置为可调用的事实。因此,为了绕过管理员对 auto_now 的特殊处理,您可以像这样声明该字段:重要的是不要使用
timezone.now()
因为默认值不会更新(即,仅在加载代码时才设置默认值)。如果您发现自己经常这样做,您可以创建一个自定义字段。然而,我认为这已经相当干燥了。I think the easiest (and maybe most elegant) solution here is to leverage the fact that you can set
default
to a callable. So, to get around admin's special handling of auto_now, you can just declare the field like so:It's important that you don't use
timezone.now()
as the default value wouldn't update (i.e., default gets set only when the code is loaded). If you find yourself doing this a lot, you could create a custom field. However, this is pretty DRY already I think.在这里,我们创建并更新了列,并在创建时以及某人修改反馈时添加了时间戳。
auto_now_add
将设置创建实例的时间,而auto_now
将设置某人修改反馈的时间。Here, we have created and updated columns with a timestamp when created, and when someone modified feedback.
auto_now_add
will set the time when an instance is created whereasauto_now
will set the time when someone modified his feedback.如果您像这样更改模型类:
那么该字段将显示在我的管理更改页面中
If you alter your model class like this:
Then this field will show up in my admin change page
根据我所读到的内容以及迄今为止使用 Django 的经验,auto_now_add 是有问题的。我同意jthanism——覆盖正常的保存方法,它很干净,你知道发生了什么。现在,为了使其干燥,创建一个名为 TimeStamped 的抽象模型:
然后,当您想要一个具有这种时间戳行为的模型时,只需子类化:
如果您希望字段显示在管理中,则只需删除
editable=False
选项Based on what I've read and my experience with Django so far, auto_now_add is buggy. I agree with jthanism --- override the normal save method it's clean and you know what's hapenning. Now, to make it dry, create an abstract model called TimeStamped:
And then, when you want a model that has this time-stampy behavior, just subclass:
If you want the fields to show up in admin, then just remove the
editable=False
option不,Django 在保存模型时会自动为您添加它,因此,这是预期的。
由于这些字段是自动添加的,因此不会显示。
添加到上面,正如 synack 所说,django 邮件列表上一直存在关于删除此内容的争论,因为它“设计得不好”并且是“黑客”
显然,您不必将其写入每个模型。您可以将其写入一个模型并从中继承其他模型。
但是,由于
auto_add
和auto_now_add
存在,我会使用它们而不是尝试自己编写方法。No, Django automatically adds it for you while saving the models, so, it is expected.
Since these fields are auto added, they are not shown.
To add to the above, as synack said, there has been a debate on the django mailing list to remove this, because, it is "not designed well" and is "a hack"
Obviously you don't have to write it to every model. You can write it to one model and inherit others from it.
But, as
auto_add
andauto_now_add
are there, I would use them rather than trying to write a method myself.至于您的管理员显示,请参阅此答案。
注意:默认情况下,
auto_now
和auto_now_add
设置为editable=False
,这就是适用的原因。As for your Admin display, see this answer.
Note:
auto_now
andauto_now_add
are set toeditable=False
by default, which is why this applies.我今天在工作中需要类似的东西。默认值为
timezone.now()
,但在继承自FormMixin
的管理视图和类视图中均可编辑,因此在我的models.py
中创建> 以下代码满足了这些要求:对于
DateTimeField
,我想从函数中删除.date()
并将datetime.date
更改为 < code>datetime.datetime 或更好的timezone.datetime
。我还没有尝试过使用DateTime
,仅使用Date
。I needed something similar today at work. Default value to be
timezone.now()
, but editable both in admin and class views inheriting fromFormMixin
, so for created in mymodels.py
the following code fulfilled those requirements:For
DateTimeField
, I guess remove the.date()
from the function and changedatetime.date
todatetime.datetime
or bettertimezone.datetime
. I haven't tried it withDateTime
, only withDate
.auto_now=True
在 Django 1.4.1 中对我不起作用,但下面的代码救了我。它适用于时区感知的日期时间。auto_now=True
didn't work for me in Django 1.4.1, but the below code saved me. It's for timezone aware datetime.您可以使用
timezone.now()
进行创建,使用auto_now
进行修改:如果您使用自定义主键而不是默认的
auto-increment int
code>,auto_now_add
将导致错误。这是Django默认 DateTimeField 的代码.pre_save 与
auto_now
和auto_now_add
:我不确定参数
add
是什么。我希望它会是这样的:You can use
timezone.now()
for created andauto_now
for modified:If you are using a custom primary key instead of the default
auto- increment int
,auto_now_add
will lead to a bug.Here is the code of Django's default DateTimeField.pre_save with
auto_now
andauto_now_add
:I am not sure what the parameter
add
is. I hope it will some thing like:您可以使用此代码技术来创建[创建日期](在创建行时自动保存日期,并且不会在每次更新时更新日期和时间)和[更新日期](每次更新行时都会更改日期和时间)。
you can use this code technique for make a [creation date] (that automatically save date at creation of row and never update the date and time on every updation ) and a [updation date] (that change date and time every time when you update the row).
关于 update_fields 已有一些评论,但尚未包含在答案中,因此我在这里进行了重要的修订。默认情况下,当 django 保存实例时,它会保存该实例中的每个字段。当只更新一个字段时,这是一种浪费,更经济的方法是只保存正在更改的字段。这是在 django 中使用 update_fields 参数完成的,如下所示:
现在您的保存方法应该考虑到这一点,否则在上面的保存中,last_modified 字段也不会保存(请注意,我不确定创建的情况,但由于您可以创建一个新实例,并使用带有更新字段的保存方法,因此我还在保存中包含条件):
Some comments have been made about update_fields, but it has not been included in an answer, so I am placing an important revision here. By default when django saves an instance, it saves every field in that instance. This is wasteful when only one field is being updated, and a more economical method is to only save the field being changed. This is done in django by using the update_fields parameter as in:
Now your save method should take this into consideration, otherwise in the above save, the last_modified field is not also saved (Note that I am not sure about created, but as you could create a new instance, and use save method with update fields, I also include the condition in the save):
如文档中报道的那样:
Such as is reported in docs: