Django+Ajax点赞功能like_count数值翻倍异常求助
问题分析与解决方案
你的点赞按钮数值增减两次的核心原因是后端修改数据库数值 + 前端不等待响应直接本地修改的双重操作,再加上代码中的几处逻辑错误,导致数据更新重复。以下是具体问题和修复步骤:
核心问题点
- 重复数值更新:后端视图已经修改了数据库中的
likes_count,但前端在Ajax请求发送后立刻手动增减数值,导致数值被修改两次。 - 视图响应错误:Ajax是异步请求,不需要重定向,但你的视图返回了
HttpResponseRedirect,既不符合异步场景需求,也可能引发额外的页面行为。 - 模型与视图字段不匹配:模型定义的多对多字段是
favs,但视图中使用了post.likes.all(),这会导致点赞状态判断完全失效(如果模型没有likes字段会直接报错,若为笔误则逻辑混乱)。 - 前端依赖旧数据:前端使用页面加载时的旧点赞数计算新值,而非后端返回的最新数据,容易出现数据不一致。
修复步骤
1. 修正视图逻辑,返回JSON数据
将视图改为返回包含最新点赞状态和点赞数的JSON,同时修复字段匹配问题:
from django.http import JsonResponse from django.db.models import F # 用于避免并发竞态条件 class AddLike(LoginRequiredMixin, View): def post(self, request, pk, *args, **kwargs): post = Post.objects.get(pk=pk) # 高效判断用户是否已点赞 is_liked = post.favs.filter(id=request.user.id).exists() if not is_liked: post.favs.add(request.user) post.likes_count = F('likes_count') + 1 # 用F表达式避免并发问题 else: post.favs.remove(request.user) post.likes_count = F('likes_count') - 1 post.save() post.refresh_from_db() # 刷新获取最新数值 # 返回JSON给前端 return JsonResponse({ 'likes_count': post.likes_count, 'is_liked': not is_liked # 返回当前最新的点赞状态 })
2. 调整前端Ajax逻辑,等待响应后更新DOM
把DOM修改逻辑移到Ajax的success回调中,完全依赖后端返回的最新数据,避免本地旧值干扰:
$(document).on('submit','#like-post',function(e){ e.preventDefault(); var $form = $(this); var pkey = $form.find('input[name="pk"]').val(); // 用name选择更可靠,避免索引错误 $.ajax({ type:'POST', url:"/social/post/"+pkey+"/like", data:{ csrfmiddlewaretoken:$form.find('input[name=csrfmiddlewaretoken]').val(), }, success: function(response){ // 用后端返回的最新数据更新页面 $('#count'+pkey).text(response.likes_count); if (response.is_liked) { $('#no-like' + pkey).hide(); $('#liked' + pkey).show(); } else { $('#no-like' + pkey).show(); $('#liked' + pkey).hide(); } }, error: function(){ console.log('点赞操作失败'); } }); });
3. 优化HTML(可选)
移除不需要的like-count隐藏输入,改用后端返回数据,同时修正模板中的字段引用:
<form method="POST" id="like-post"> {% csrf_token %} <input type="hidden" name="next" value="{{ request.path }}"> <input type="hidden" name="pk" value="{{ post.pk }}"> <button style="background-color: transparent; border: none; box-shadow: none;" type="submit"> <span id="count{{ post.pk }}">{{ post.likes_count }}</span> {% if request.user in post.favs.all %} <i id="no-like{{ post.pk }}" style="color:gray; display: none;" class="fa-solid fa-champagne-glasses"></i> <i id="liked{{ post.pk }}" style="color:green;" class="fa-solid fa-champagne-glasses"></i> {% else %} <i id="liked{{ post.pk }}" style="color:green; display: none;" class="fa-solid fa-champagne-glasses"></i> <i id="no-like{{ post.pk }}" style="color:gray;" class="fa-solid fa-champagne-glasses"></i> {% endif %} </button> </form>
内容的提问来源于stack exchange,提问作者João Branco
相关产品推荐
相关产品推荐

