代码之家  ›  专栏  ›  技术社区  ›  HTML

姜戈。在不影响其updated_at字段的情况下增加对象的视图数

  •  0
  • HTML  · 技术社区  · 2 年前

    我有以下型号:

    class Announcement(models.Model):
        ...
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)
        views = models.PositiveIntegerField(default=0, editable=False)
    

    我的观点:

    class AnnouncementDetailView(DetailView):
        model = Announcement
        context_object_name = 'announcement'
        template_name = 'web/index.html'
    
        def get(self, *args, **kwargs):
            announcement = get_object_or_404(Announcement, id=kwargs['id'])
            announcement.views += 1
            announcement.save()
            return super().get(self, *args, **kwargs)
    

    问题在于:

    1. 我知道 F 表达式,我将在下面使用它,但我想知道更新字段和不更新 更新日期 领域
    2. 我想保存对模型的更改 views 字段,但每次保存时,都会将新值设置为 updated_at 领域这意味着每当我刷新页面时,它都会显示当前时间 更新日期 田,这是非常糟糕的。

    我已将视图的代码更改为:

    ...
    def get(self, *args, **kwargs):
        Announcement.objects.filter(id=kwargs['id']).update(views=F('views') + 1)
        return super().get(self, *args, **kwargs)
    

    现在它运行良好,但我有几个问题。它如何保存 视图 字段而不调用 拯救 “”“Django”“的方法?我能用它走多远。在不影响 拯救 方法

    0 回复  |  直到 2 年前
        1
  •  1
  •   willeM_ Van Onsem    2 年前

    一个简单的方法可以是指定 update_fields .save(…) method [Django-doc] :

    class AnnouncementDetailView(DetailView):
        model = Announcement
        context_object_name = 'announcement'
        template_name = 'web/index.html'
    
        def get(self, *args, **kwargs):
            try:
                return super().get(self, *args, **kwargs)
            finally:
                object = getattr(self, 'object', None)
                if object:
                    object.views = F('views') + 1
                    object.save(update_fields=('views',))

    然而,最好使用 F -要避免的表达式 比赛条件

    利用:

    Announcement.objects.filter(id=kwargs['id']).update(views=F('views') + 1)
    

    将允许数据库进行如下查询:

    UPDATE appname_announcement
    SET view = view + 1
    WHERE id = id

    因此,如果您不必在内存中加载对象,这将更加高效,因为它只需往返数据库一次。