【问题标题】:Django. Increment views count of object without affecting its updated_at field姜戈。在不影响其 updated_at 字段的情况下增加对象的查看次数
【发布时间】:2022-11-13 23:01:55
【问题描述】:

我有以下模型:

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)
    

    现在它工作正常,但我有几个问题。它如何保存views 字段的新值而不调用节省""""Django""""" 的方法?我能用它走多远。改变模型的某些领域而不击中的最佳实践是什么节省方法?

    在此先感谢您的广泛解释!

【问题讨论】:

    标签: python django database django-models


    【解决方案1】:

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

    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-expression 来避免竞争条件.

    利用:

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

    将让数据库进行如下查询:

    更新应用名称_公告
    放视图 = 视图 + 1哪里 id =ID

    如果您因此不必将对象加载到内存中,这将更有效,因为它只往返于数据库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-29
      • 2018-02-01
      • 2012-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-27
      • 2016-07-02
      相关资源
      最近更新 更多