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

Rog*_*ger 126 python django django-models

自动设置对象的创建日期的最佳方法是什么,以及将在上次更新对象时记录的字段?

在我的模型中,我有:

created_at = models.DateTimeField(False, True, editable=False)
updated_at = models.DateTimeField(True, True, editable=False)
Run Code Online (Sandbox Code Playgroud)

在我看来:

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')
Run Code Online (Sandbox Code Playgroud)

我收到错误:

objects_object.created_at may not be NULL
Run Code Online (Sandbox Code Playgroud)

我是否必须自己手动设置此值?我认为这是传递给DateTimeFields的参数点(或者它们只是默认值,因为我设置'editable = False'它们不会显示在表单上,​​因此不会在请求中提交,因此不要进入表格?).

这样做的最佳方法是什么?一个init方法?

谢谢

ps - 我是django和Python的新手......

Man*_*dan 268

您可以使用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)
Run Code Online (Sandbox Code Playgroud)

  • `auto_now`和`auto_now_add`被认为是邪恶的,所以尽量避免它们.[这个答案](http://stackoverflow.com/a/1737078/1226722)解释了为什么并提供了一种更好的方法,覆盖了`save()`方法. (23认同)
  • 我认为 @gregoltsov 的评论目前已经过时了。使用“auto_now_add”或“auto_now”效果很好。它在保存模型之前设置字段(https://github.com/django/django/blob/stable/3.0.x/django/db/models/fields/__init__.py#L1343)。 (6认同)
  • [Django REST Framework 似乎认为这是一个很好的方法](https://www.django-rest-framework.org/api-guide/fields/#auto_now-and-auto_now_add-model-fields)。 (4认同)
  • 它产生了这个错误:`你试图在没有默认值的情况下向gameuser添加一个不可为空的字段'created_at'; 我们不能那样做(数据库需要一些东西来填充现有的行).请选择一个修复:1)现在提供一次性默认(将在所有现有行上设置)2)退出,让我在models.py中添加默认值选择一个选项:1请现在输入默认值,如有效的Python datetime和django.utils.timezone模块是可用的,所以你可以做例如timezone.now()>>> timezone.now()` (3认同)
  • 删除数据库上的行,或选中选项 1 并添加 timezone.now() (2认同)

Chi*_*xit 9

好吧,上面的答案是正确的,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
Run Code Online (Sandbox Code Playgroud)

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

class Posts(TimeStampMixin):
    name = models.CharField(max_length=50)
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

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

  • 很快你就会发现自己有 7 层继承,但不明白到底发生了什么……或者更好的是 7 层继承被折叠成一个名为“Utility”的类。 (11认同)