对于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,
这值得关注吗?
小问题:在我的管理工具中,这两个字段没有显示。这是意料之中的吗?
我今天工作也需要类似的东西。默认值是时区.now(),但可编辑的管理和类视图继承自FormMixin,所以创建在我的models.py下面的代码满足这些要求:
from __future__ import unicode_literals
import datetime
from django.db import models
from django.utils.functional import lazy
from django.utils.timezone import localtime, now
def get_timezone_aware_now_date():
return localtime(now()).date()
class TestDate(models.Model):
created = models.DateField(default=lazy(
get_timezone_aware_now_date, datetime.date)()
)
对于DateTimeField,我想从函数中删除.date()并更改datetime。日期到日期时间。Datetime或者更好的timezone.datetime。我没有在DateTime上尝试过,只在Date上尝试过。
带有auto_now属性集的任何字段也将继承editable=False,因此不会显示在管理面板中。过去已经讨论过删除auto_now和auto_now_add参数,尽管它们仍然存在,但我认为最好使用自定义save()方法。
因此,为了使其正常工作,我建议不要使用auto_now或auto_now_add,而是定义自己的save()方法,以确保仅在未设置id时(例如当项目第一次创建时)才更新created,并在每次保存项目时更新修改它。
我用Django写的其他项目也做了同样的事情,所以你的save()看起来像这样:
from django.utils import timezone
class User(models.Model):
created = models.DateTimeField(editable=False)
modified = models.DateTimeField()
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.created = timezone.now()
self.modified = timezone.now()
return super(User, self).save(*args, **kwargs)
根据意见进行编辑:
为什么我只是坚持重载save()而不是依赖这些字段参数的原因有两个:
The aforementioned ups and downs with their reliability. These arguments are heavily reliant on the way each type of database that Django knows how to interact with treats a date/time stamp field, and seems to break and/or change between every release. (Which I believe is the impetus behind the call to have them removed altogether).
The fact that they only work on DateField, DateTimeField, and TimeField, and by using this technique you are able to automatically populate any field type every time an item is saved.
Use django.utils.timezone.now() vs. datetime.datetime.now(), because it will return a TZ-aware or naive datetime.datetime object depending on settings.USE_TZ.
为了解决OP看到错误的原因,我不确切地知道,但它看起来像创建的甚至没有被填充,尽管有auto_now_add=True。对我来说,这是一个明显的错误,并强调了我上面小列表中的第一条:auto_now和auto_now_add充其量是不可靠的。
根据我所读到的和我目前使用Django的经验,auto_now_add是有bug的。我同意jthanism,重写正常的保存方法,这很干净,你知道发生了什么。现在,为了使它变干,创建一个名为TimeStamped的抽象模型:
from django.utils import timezone
class TimeStamped(models.Model):
creation_date = models.DateTimeField(editable=False)
last_modified = models.DateTimeField(editable=False)
def save(self, *args, **kwargs):
if not self.creation_date:
self.creation_date = timezone.now()
self.last_modified = timezone.now()
return super(TimeStamped, self).save(*args, **kwargs)
class Meta:
abstract = True
然后,当你想要一个具有这种时间戳行为的模型时,只需子类:
MyNewTimeStampyModel(TimeStamped):
field1 = ...
如果您希望字段显示在管理中,那么只需删除editable=False选项