Django DetailView访问计数每次递增3而非预期1的问题排查
问题根因
计数每次加3是因为get_object()方法总共被调用了3次,每次调用都会执行views_count自增+存库的逻辑:
- Django类视图
DetailView的标准执行流程本身会自动调用1次get_object()获取要渲染的模型实例,触发第一次计数+1 - 你在
get_context_data方法中写了两次self.get_object()调用,分别用于查询关联链接、关联电影,这两次调用会各自再触发一次计数+1 - 三次调用累加,最终表现为单次页面访问计数加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
相关产品推荐
相关产品推荐

