对于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,

这值得关注吗?

小问题:在我的管理工具中,这两个字段没有显示。这是意料之中的吗?


当前回答

这值得关注吗?

不,在保存模型时,Django会自动为你添加它,所以,这是意料之中的。

辅助问题:在我的管理工具中,这两个字段没有显示。这是意料之中的吗?

由于这些字段是自动添加的,所以不会显示它们。

为了补充上面的内容,正如synack所说,django邮件列表中一直有关于删除它的争论,因为它“设计得不好”,是“一个黑客”。

在我的每个模型上编写自定义save()比使用auto_now要痛苦得多

显然,你不需要对每个模型都写。您可以将它写入一个模型,并从它继承其他模型。

但是,由于存在auto_add和auto_now_add,我宁愿使用它们,而不是自己尝试编写方法。

其他回答

带有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充其量是不可靠的。

auto_now=True在Django 1.4.1中并不适用,但是下面的代码拯救了我。它用于时区感知datetime。

from django.utils.timezone import get_current_timezone
from datetime import datetime

class EntryVote(models.Model):
    voted_on = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        self.voted_on = datetime.now().replace(tzinfo=get_current_timezone())
        super(EntryVote, self).save(*args, **kwargs)

你可以使用timezone.now()来创建,auto_now来修改:

from django.utils import timezone
class User(models.Model):
    created = models.DateTimeField(default=timezone.now())
    modified = models.DateTimeField(auto_now=True)

如果使用自定义主键而不是默认的自增整型,auto_now_add将导致错误。

下面是Django默认DateTimeField的代码。Pre_save withauto_now和auto_now_add:

def pre_save(self, model_instance, add):
    if self.auto_now or (self.auto_now_add and add):
        value = timezone.now()
        setattr(model_instance, self.attname, value)
        return value
    else:
        return super(DateTimeField, self).pre_save(model_instance, add)

我不确定add参数是什么。我希望它会像这样:

add = True if getattr(model_instance, 'id') else False

新记录将没有attr id,因此getattr(model_instance, 'id')将返回False,将导致在字段中不设置任何值。

说一个题外话:如果你想在管理中看到这些字段(虽然,你不能编辑它),你可以把readonly_fields添加到你的管理类中。

class SomeAdmin(ModelAdmin):
    readonly_fields = ("created","modified",)

好吧,这只适用于最新的Django版本(我相信是1.3及以上版本)

class Feedback(models.Model):
    feedback = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

在这里,我们创建了列,并在列创建时和有人修改反馈时使用时间戳进行更新。

Auto_now_add将设置实例创建的时间,而auto_now将设置某人修改反馈的时间。