Django点赞功能if和else均执行导致显示两个点赞按钮如何解决
问题根因
你模板中错误遍历了单条回答的所有点赞记录:只要回答有多个用户点赞,就会为每条点赞记录生成一个按钮,自然会同时出现「已点赞」「未点赞」多个按钮,和if/else分支执行逻辑无关。
修复步骤
1. 优化视图层,提前注入用户点赞状态
在question_detail视图里用Django的Exists注解直接给每个回答加上当前用户是否点赞的标记,避免模板层反复查询数据库:
from django.db.models import Exists, OuterRef def question_detail(request, question_id): post = get_object_or_404(Question, pk=question_id) # 给每个回答标注当前用户是否点赞 answers = post.answer_set.annotate( is_liked=Exists( AnswerLike.objects.filter( answer_of=OuterRef('pk'), liked_by=request.user if request.user.is_authenticated else None ) ) ) context = {'post':post, 'answers':answers} return render(request, 'question_detail.html', context)
2. 重写模板逻辑,删除点赞记录遍历
不要循环ans.answerlike_set.all,直接用视图传的is_liked字段判断即可:
{{post}} {% for ans in answers %} {{ans.body}} <form method="POST" class="AnswerLike" action="{% url 'answer_like' ans.id %}"> {% csrf_token %} {% if ans.is_liked %} <button name='submit' type='submit' value="UnLike"><i class="fas fa-thumbs-up"></i>Liked</button> {% else %} <button name='submit' type='submit' value="Like"><i class="far fa-thumbs-up"></i>Not Liked</button> {% endif %} </form> {% endfor %}
3. 补全点赞视图的取消逻辑
同时建议把请求方法改成POST,避免GET请求误触发修改操作:
from django.shortcuts import get_object_or_404 from django.http import JsonResponse from django.views.decorators.http import require_http_methods @require_http_methods(["POST"]) def answer_like(request, answer_id): answer = get_object_or_404(Answer, pk=answer_id) user = request.user if not user.is_authenticated: return JsonResponse({'status':'unlogin'}, status=403) # 先查有没有点赞记录 like_obj = AnswerLike.objects.filter(answer_of=answer, liked_by=user).first() if request.POST.get('submit') == 'Like': # 没有就创建 if not like_obj: AnswerLike.objects.create(answer_of=answer, liked_by=user) return JsonResponse({'status':'liked'}) elif request.POST.get('submit') == 'UnLike': # 有就删除 if like_obj: like_obj.delete() return JsonResponse({'status':'unliked'})
额外优化建议
可以给AnswerLike模型加联合唯一约束,避免同一个用户给同一条回答重复点赞:
class AnswerLike(models.Model): answer_of = models.ForeignKey(Answer, on_delete=models.CASCADE) liked_by = models.ForeignKey(User, on_delete=models.CASCADE) class Meta: constraints = [ models.UniqueConstraint(fields=['answer_of', 'liked_by'], name='unique_user_answer_like') ]
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

