【问题标题】:Django auto_now behaviourDjango auto_now 行为
【发布时间】:2018-02-01 03:14:45
【问题描述】:

我有以下型号:

class MetaData(models.Model):
    created_at = models.DateTimeField(auto_now_add=True, auto_now=False)
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,
                                   related_name='%(app_label)s_%(class)s_created_by')
    updated_at = models.DateTimeField(auto_now_add=False, auto_now=True)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
                                   related_name='%(app_label)s_%(class)s_updated_by')

update_at 字段也在创建时以一个值完成,而不是为空。我希望只有在第一次保存/创建之后才会有一个值。

我做错了吗?

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    在 Django 中,您同时拥有 auto_nowauto_now_add

    来自文档:

    DateField.auto_now

    在每次保存对象时自动将字段设置为现在。(这意味着它也是第一次创建时)

    DateField.auto_now_add

    在第一次创建对象时自动将字段设置为现在

    编辑

    如果您希望在首次创建对象时将 updated_at 字段设为 null,您只需将 null=Trueauto_now=True 一起传递给 DateTimeField

    class MetaData(models.Model):
        # ...
        updated_at = models.DateTimeField(auto_now=True, null=True)
        # ...
    

    【讨论】:

    • 有什么办法可以覆盖这个行为?
    • @user3541631 我刚刚用可能的解决方案编辑了我的答案。
    • @user3541631 最好看看这个关于使用 auto_now 和 auto_now_add stackoverflow.com/questions/1737017/…
    • @wencakisa 你确定“auto_now=True, null=True”会起作用吗?刚刚在 Postgres DB 上测试过它并没有。我也看不到 Postgress 上的实现是如何实现的
    • @zoran,正如您已经指出的那样,我还确认 updated_at = models.DateTimeField(auto_now=True, null=True) 确实 not(!) 工作。每次保存对象时都会设置它(包括创建记录时)。注意:使用 django 3.0.4 测试
    【解决方案2】:

    还有另一种方法可以做到这一点。最好按照wencakisa 的建议做,除非您在模型中使用save 方法。

    正如documentation中所写的那样

    该字段仅在调用 Model.save() 时自动更新。这 以其他方式更新其他字段时,字段未更新 例如 QuerySet.update(),尽管您可以为 像这样的更新中的字段。

    所以,即使你使用auto_now,但是调用save方法例如生成一个slug地址,时间也会在对象创建时分配给auto_now的字段。

    如何处理这种情况并在创建之后和更新之前将字段updated_at 保留为null 值?

    例如,如果您使用的是 UpdateView,请在 form_valid 方法中指定时间。

    models.py

    class MetaData(models.Model):
        created_at = models.DateTimeField(auto_now_add=True, auto_now=False)
        created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,
                                       related_name='%(app_label)s_%(class)s_created_by')
        updated_at = models.DateTimeField(null=True)
        updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
                                       related_name='%(app_label)s_%(class)s_updated_by')
    
        def save(self, *args, **kwargs):
            # SOMETHING HERE
            super().save(*args, **kwargs)
    

    views.py

    class UpdateMetaData(generic.UpdateView):
        # SOMETHING HERE
    
        def form_valid(self, form):
            self.object = form.save(commit=False)
            self.object.updated_at = timezone.now()
            self.object.save()
            return super().form_valid(form)
    

    您应该在创建后拥有updated_atnull 值,并在更新字段后拥有正确的时间值。

    我认为同样的方式你也可以将更新作者分配给updated_by

    【讨论】:

      猜你喜欢
      • 2021-04-20
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 2010-09-06
      • 2018-06-27
      • 2013-02-14
      • 1970-01-01
      • 2021-12-23
      相关资源
      最近更新 更多