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

解决Django评论点赞按钮点击出现NoReverseMatch错误且Ajax无法自动更新的问题

解决Django评论点赞的NoReverseMatch错误及Ajax状态更新问题

看起来你遇到的核心问题是Ajax请求的URL路径不完整,导致Django找不到对应的路由,同时还有几个小细节(比如重复ID、CSRF传递方式)影响了功能正常工作。让我们一步步解决:

问题根源分析

  1. 路由路径不匹配:你的URL配置是post/<int:pk>/like-comment,但Ajax请求里直接用了"like-comment",缺少了前面的post/<post_id>/部分,Django无法解析这个路由,所以抛出NoReverseMatch。
  2. 静态JS无法解析模板变量:你的main.js是静态文件,里面的{{ csrf_token }}不会被Django模板引擎渲染,导致CSRF token传递错误(虽然你加了csrf_exempt,但这不是最佳实践)。
  3. 重复DOM ID:所有评论的点赞按钮都用了id="like-comment",DOM中ID必须唯一,这会导致点击事件绑定混乱,只有第一个按钮能正常触发。

分步解决方案

1. 修正Ajax请求的URL和CSRF传递方式(main.js)

把选择器从ID改成class,构建完整的URL,并从页面元标签获取CSRF token:

$(document).ready(function(){
    // 用class选择器绑定事件,避免重复ID问题
    $(document).on('click', '.like-comment-btn', function(event){
        event.preventDefault();
        const commentId = $(this).val(); // 评论ID
        const postId = $(this).data('post-id'); // 帖子ID
        // 构建完整的请求URL
        const url = `/post/${postId}/like-comment`;
        // 从页面元标签获取CSRF token
        const csrfToken = $('meta[name="csrf-token"]').attr('content');

        $.ajax({
            type: 'POST',
            url: url,
            data: {
                'id': commentId,
                'csrfmiddlewaretoken': csrfToken
            },
            dataType: 'json',
            success: function(response) {
                // 更新对应评论的点赞区域,用唯一ID定位
                $(`#like-section-comment-${commentId}`).html(response.form);
            },
            error: function(rs, e) {
                console.error('点赞请求失败:', rs.responseText);
            },
        });
    });
});

2. 修改评论模板,确保唯一标识(comment_section.html)

给每个评论的点赞区域添加唯一ID,同时把按钮的ID改成class:

<article class="media content-section">
    {% if user.is_authenticated %}
    <!-- 给每个评论的点赞区域加唯一ID,方便Ajax更新 -->
    <div id="like-section-comment-{{ comment.id }}">
        <form method="post">
            {% csrf_token %}
            {% if request.user in comment.likes.all %}
            <button type="submit" class="like-comment-btn btn btn-danger btn-sm" 
                    name="comment_id" data-post-id="{{ comment.post.id }}" 
                    value="{{ comment.id }}">
                Dislike
            </button>
            {% else %}
            <button type="submit" class="like-comment-btn btn btn-primary btn-sm" 
                    name="comment_id" data-post-id="{{ comment.post.id }}" 
                    value="{{ comment.id }}">
                Like
            </button>
            {% endif %}
            <span class="ml-2">{{ comment.likes.count }} 赞</span>
        </form>
    </div>
    {% endif %}
</article>

同时确保你的base.html里有CSRF元标签(如果没有的话加上):

<meta name="csrf-token" content="{{ csrf_token }}">

3. 优化视图函数(可选,移除csrf_exempt)

既然我们已经正确传递了CSRF token,就可以去掉@csrf_exempt装饰器,恢复CSRF保护:

# 移除@csrf_exempt
def like_comment(request, pk):
    comment = get_object_or_404(Comment, id=request.POST.get('id'))
    liked = False
    if comment.likes.filter(id=request.user.id).exists():
        comment.likes.remove(request.user)
        liked = False
    else:
        comment.likes.add(request.user)
        liked = True
    context = {
        'comment': comment,
        'is_liked': liked,
        'total_likes': comment.likes.count()
    }
    if request.headers.get('x-requested-with') == 'XMLHttpRequest': # 更准确的Ajax判断
        html = render_to_string('blog/like_section_comment.html', context, request=request)
        return JsonResponse({'form': html})
    return redirect('post-detail', pk=pk) # 非Ajax请求的 fallback

4. 确保like_section_comment.html模板正确

你的like_section_comment.html应该是评论点赞区域的片段,和上面模板里的内容一致,比如:

<form method="post">
    {% csrf_token %}
    {% if is_liked %}
    <button type="submit" class="like-comment-btn btn btn-danger btn-sm" 
            name="comment_id" data-post-id="{{ comment.post.id }}" 
            value="{{ comment.id }}">
        Dislike
    </button>
    {% else %}
    <button type="submit" class="like-comment-btn btn btn-primary btn-sm" 
            name="comment_id" data-post-id="{{ comment.post.id }}" 
            value="{{ comment.id }}">
        Like
    </button>
    {% endif %}
    <span class="ml-2">{{ total_likes }} 赞</span>
</form>

测试验证

  1. 重启Django服务器
  2. 打开帖子页面,点击任意评论的点赞按钮,应该能看到按钮立即切换成Dislike/Like,点赞数同步更新,页面无需刷新
  3. 检查浏览器控制台,如果还有错误,查看Network面板里的请求URL是否正确(应该是/post/[post_id]/like-comment)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 06:57:34