Django模型字段更新问题:点赞/踩赞按钮均触发双计数
解决Django中点赞/踩赞计数同时增加的问题
嘿,我来帮你搞定这个问题!你遇到的核心情况是:不管点不点链接,页面加载时Like和Dislike的计数就已经自动涨了,这才导致每次操作两个数值都会同步增加。下面我一步步给你拆解原因和解决方案:
问题根源
你在模板里写了{{ object.like_this_movie }}和{{ object.dislike_this_movie }},在Django模板中,这种写法会直接调用模型的方法(因为方法没有参数)。也就是说,当页面渲染的那一刻,这两个方法就已经执行了——不管你点没点击链接,Like和Dislike的数值已经各加1了。点击链接只是跳转到方法返回的URL,但计数早就提前更新过了。
正确的解决方案
我们需要把点赞/踩赞的逻辑从模型移到视图中,通过URL映射来处理点击请求,这样只有当用户主动点击链接时才会触发计数更新。
1. 修改模型(models.py)
去掉模型里的like_this_movie和dislike_this_movie方法,同时给Like/Dislike字段加上默认值(避免新建电影时出现空值错误):
from django.db import models from django.urls import reverse class Movies(models.Model): Director=models.CharField(max_length=30) Cast_I=models.CharField(max_length=30) Cast_II=models.CharField(max_length=30) Name=models.TextField() ReleaseYear=models.IntegerField() ImdbRating=models.CharField(max_length=2) Genre=models.TextField(null=True) Language=models.CharField(max_length=20,null=True) Like=models.IntegerField(default=0) # 添加默认值0 Dislike=models.IntegerField(default=0) # 添加默认值0 # 可选:添加get_absolute_url,方便跳转回详情页 def get_absolute_url(self): return reverse('detail', kwargs={'pk': self.pk})
2. 配置URL(urls.py)
新增两个URL,分别对应点赞和踩赞的视图:
from django.urls import path from .views import MovieDetailView, like_movie, dislike_movie urlpatterns = [ path('movie/<int:pk>/', MovieDetailView.as_view(), name='detail'), path('movie/<int:pk>/like/', like_movie, name='like_movie'), path('movie/<int:pk>/dislike/', dislike_movie, name='dislike_movie'), ]
3. 编写处理逻辑的视图(views.py)
创建两个视图函数,专门处理点赞和踩赞的请求:
from django.shortcuts import get_object_or_404, redirect from .models import Movies from django.views.generic import DetailView class MovieDetailView(DetailView): template_name='movie/detail.html' queryset=Movies.objects.all() context_object_name = 'object' # 保持模板中变量名一致 def like_movie(request, pk): # 获取对应的电影对象,不存在则返回404 movie = get_object_or_404(Movies, pk=pk) movie.Like += 1 movie.save() # 更新后跳回电影详情页 return redirect('detail', pk=pk) def dislike_movie(request, pk): movie = get_object_or_404(Movies, pk=pk) movie.Dislike += 1 movie.save() return redirect('detail', pk=pk)
4. 修改模板文件
把原来的链接改成指向我们刚配置的URL,同时可以显示当前的计数:
{% block content %} <p> <a href="{% url 'like_movie' object.pk %}">Like ({{ object.Like }})</a> <a href="{% url 'dislike_movie' object.pk %}">Dislike ({{ object.Dislike }})</a> </p> {% endblock %}
额外提示
- 如果你想防止用户重复点赞/踩赞,可以考虑添加用户和电影的关联记录(比如用
ManyToManyField),或者用session/cookie来限制同一用户的操作。 - 生产环境中,建议用
F()表达式来更新计数,避免并发问题:比如movie.Like = F('Like') + 1,这样可以在数据库层面原子更新,防止多用户同时操作时计数出错。
内容的提问来源于stack exchange,提问作者Nayan
相关产品推荐
相关产品推荐

