You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django DetailView访问计数每次递增3而非预期1的问题排查

问题根因

计数每次加3是因为get_object()方法总共被调用了3次,每次调用都会执行views_count自增+存库的逻辑:

  1. Django类视图DetailView的标准执行流程本身会自动调用1次get_object()获取要渲染的模型实例,触发第一次计数+1
  2. 你在get_context_data方法中写了两次self.get_object()调用,分别用于查询关联链接、关联电影,这两次调用会各自再触发一次计数+1
  3. 三次调用累加,最终表现为单次页面访问计数加3。
修复方法

核心原则是两点:一是计数逻辑只在单次请求中执行1次,二是不要重复调用get_object()获取已经拿到的实例,DetailView会把首次获取到的模型实例存在self.object属性里,直接复用即可。
另外推荐使用Django内置的F()表达式做计数更新,避免多用户并发访问时出现计数覆盖不准的问题。

修正后的views.py代码如下:

from django.db.models import F
from django.views.generic import ListView, DetailView
from .models import Movie, MovieLink

class MovieDetail(DetailView):
    model = Movie

    def get_object(self, queryset=None):
        movie_obj = super().get_object(queryset=queryset)
        # 数据库层面执行自增,避免并发场景下计数错误
        movie_obj.views_count = F('views_count') + 1
        movie_obj.save(update_fields=['views_count'])
        # 刷新对象拿到更新后的最新计数值
        movie_obj.refresh_from_db()
        return movie_obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 直接复用已加载的实例,不再重复调用get_object()
        context['links'] = MovieLink.objects.filter(movie=self.object)
        context['related_movies'] = Movie.objects.filter(category=self.object.category)
        return context

模板代码不需要做任何修改,替换后重启服务即可实现单次访问计数+1的预期效果。


内容的提问来源于stack exchange,提问作者user19215134

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:01:18