Django模型表单对象的自动创建日期

246

如何自动设置对象的创建日期和记录上次更新时间的字段,这是最佳方法?

models.py:

created_at = models.DateTimeField(False, True, editable=False)
updated_at = models.DateTimeField(True, True, editable=False)

视图函数代码 (views.py):

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.user = request.user
        obj.save()
        return HttpResponseRedirect('obj_list')

我收到了这个错误:

objects_object.created_at may not be NULL

我需要手动设置这个值吗?我以为这就是传递给DateTimeField参数的意义所在(或者它们只是默认值,因为我设置了editable=False 所以它们不会在表单上显示,因此不会在请求中提交,因此也不会被放入表单中)。

做这件事情的最佳方式是什么?使用一个__init__方法吗?

2个回答

473

您可以使用auto_nowauto_now_add选项来分别为updated_atcreated_at设置。

class MyModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

4
出现了以下错误: “您正在尝试向gameuser添加一个非空字段'created_at',但是没有提供默认值;这样做是不行的(数据库需要一些内容来填充现有的行)。 请选择修复方式: 1)立即提供一个一次性默认值(将在所有现有行上设置) 2)退出,并让我在models.py中添加默认值 选择一个选项:1 请现在输入默认值,作为有效的Python代码 datetime和django.utils.timezone模块可用,因此您可以执行例如timezone.now()” - Kaleem Ullah
2
删除数据库中的行,或者选择选项1并添加timezone.now()。 - mullerivan
4
Django REST Framework认为这是一种可行的方法。 - phoenix
8
我认为@gregoltsov的评论现在已经过时了。使用auto_now_addauto_now完全没有问题。它会在保存模型之前设置字段(https://github.com/django/django/blob/stable/3.0.x/django/db/models/fields/__init__.py#L1343)。 - yndolok
1
感谢 @yndolok 和 Dandelion - 我已经删除了我的评论,以免让着陆在这个答案上的人感到困惑! - gregoltsov
显示剩余3条评论

115

以上答案是正确的,auto_now_addauto_now可以实现此功能,但最好创建一个抽象类,在任何需要created_atupdated_at的模型中使用。

class TimeStampMixin(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

现在,您可以在任何想要使用它的地方进行简单的继承,并且可以在您创建的任何模型中使用时间戳。

class Posts(TimeStampMixin):
    name = models.CharField(max_length=50)
    ...
    ...

通过这种方式,您可以在Django DRY(不要重复自己)中利用面向对象的可重用性


11
很快你会发现自己有了7层继承,却不明白到底发生了什么...或者更好的方法是,将7层继承合并为一个名为“Utility”的类。 - Spidey
@Spidey 我对你的评论感到矛盾:一方面,我非常同意滥用抽象化(特别是面向对象编程)往往是不好的事情。然而,在这种情况下,它似乎是一种“好的(因为它是可预测的和通常有用的)模式/实践封装”,这正是像Django等框架的本质所在。 - cjauvin
1
@cjauvin 我理解你的立场,我自己也曾经有过同样的经历,但我真诚地认为这个例子属于“组合优于继承”。从库/框架中获得灵感是可以的,但请记住,项目代码不需要像可重用性那样高。它需要快速修改,而添加继承层可能会在这方面造成损失。 - Spidey
如果每个人都有那种心态,我们就永远无法从汇编语言起飞了。 - Eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接