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

Django轻量Reddit风格应用评论点赞后重复显示问题求助

解决Django评论点赞后重复显示的问题

可能原因及修复方案

1. 模板循环嵌套错误(最常见)

如果在评论循环内部嵌套遍历了comment.likes.all(),会导致单条评论根据点赞数重复渲染。比如错误模板代码:

{% for comment in comments %}
  {% for like in comment.likes.all %}
    <div class="comment">{{ comment.content }}</div>
  {% endfor %}
{% endfor %}

修复:
删除嵌套的likes循环,仅在评论块内展示点赞数和按钮:

{% for comment in comments %}
  <div class="comment">
    <p>{{ comment.content }}</p>
    <span>点赞数: {{ comment.like_count }}</span>
    <form action="{% url 'comment_like' comment.pk %}" method="POST">
      {% csrf_token %}
      <button type="submit">
        {% if request.user in comment.likes.all %}取消点赞{% else %}点赞{% endif %}
      </button>
    </form>
  </div>
{% endfor %}

2. 评论查询集因关联查询产生重复

在BulletinDetail视图中,使用Count('likes')注解点赞数时,若未添加distinct=True,会因为ManyToMany关联产生笛卡尔积,导致评论对象重复。
错误代码:

comments = bulletin.comments.all().annotate(like_count=Count('likes'))

修复:
在Count中加入distinct=True去重:

comments = bulletin.comments.all().annotate(like_count=Count('likes', distinct=True)).order_by('-created_at')

3. AJAX处理逻辑错误

如果点赞用AJAX实现,若前端在请求成功后追加而非替换对应评论的点赞数据,会导致重复渲染评论。
修复:
前端仅更新目标评论的点赞数和按钮状态,而非重新渲染整个评论列表。示例JS代码:

document.querySelectorAll('.like-btn').forEach(btn => {
  btn.addEventListener('submit', function(e) {
    e.preventDefault();
    const commentId = this.dataset.commentId;
    fetch(this.action, {
      method: 'POST',
      headers: {'X-CSRFToken': getCookie('csrftoken')}
    }).then(res => res.json())
      .then(data => {
        const likeCount = document.querySelector(`#like-count-${commentId}`);
        const likeBtn = document.querySelector(`#like-btn-${commentId}`);
        likeCount.textContent = data.like_count;
        likeBtn.textContent = data.liked ? '取消点赞' : '点赞';
      });
  });
});

4. 模型或视图的关联配置错误

检查Comment模型的likes字段是否正确配置,避免反向关联冲突:

class Comment(models.Model):
    bulletin = models.ForeignKey(Bulletin, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    content = models.TextField()
    likes = models.ManyToManyField(User, related_name='comment_likes', blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

确保related_name与帖子的点赞字段不重复,避免查询时混淆。

排查步骤

  1. 先检查模板的评论循环逻辑,确认没有嵌套遍历likes的代码;
  2. 查看BulletinDetail视图的评论查询集,确认Count注解加了distinct=True;
  3. 若用AJAX,检查前端是否仅更新目标评论的DOM元素,而非重新加载所有评论;
  4. 验证CommentLike视图仅执行一次状态变更,且返回正确的重定向或AJAX数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 10:30:23