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

Django点赞功能点击触发Fetch时页面重载仅显示JSON数据如何解决

问题排查及修复方案

核心问题1:JS事件未生效导致表单默认提交

你在循环渲染所有帖子时,给每个点赞按钮、点赞数标签都用了相同的固定id likeButton、numOfLikes,而HTML中id属性是全局唯一的,document.getElementById('likeButton') 只能匹配到页面中第一个出现的点赞按钮,其余帖子的点赞按钮点击时根本不会触发你写的阻止默认提交逻辑,会直接触发form表单的默认跳转提交,后端返回JSON就直接显示在页面上,出现白屏展示JSON的问题。

核心问题2:Fetch请求逻辑错误

  • 请求方法不匹配:你JS里用的是PUT方法发起请求,但后端视图是从request.POST中取参数,Django默认不会解析PUT请求的参数到request.POST中,且你没有在fetch的body中传递任何参数,导致后端拿不到buttonForLikes的值。
  • 响应解析错误:你用response.text()解析后端返回的JSON,得到的是字符串而非JS对象,后续result.likeButton的判断逻辑完全失效。
  • 缺少CSRF校验头:Django对POST请求需要校验CSRF令牌,你当前的fetch请求没有携带该头,可能被拦截。

其他小问题

  • HTML中点赞按钮的class拼写成claas,"Unike"拼写错误应为"Unlike"。
  • 后端视图中重复查询Post对象,likeCount = Post.objects.get(id = post.id)是完全多余的逻辑,直接用已经查询到的post对象即可。

具体修改步骤

1. 修改HTML模板

把固定id改为动态id,避免重复:

<!-- 循环内的点赞部分修改 -->
{% if request.user in item.like.all %}
<div> 
    <button class="likes" id="likeButton_{{ item.id }}" data-id="{{ item.id }}" value="Unlike" name="buttonForLikes">
        Unlike
    </button>: 
    <span id="numOfLikes_{{ item.id }}">{{ item.like_count }}</span>
    {% csrf_token %}
</div>
{% else %}
<div> 
    <button class="likes" id="likeButton_{{ item.id }}" data-id="{{ item.id }}" value="Like" name="buttonForLikes">
        Like
    </button>: 
    <span id="numOfLikes_{{ item.id }}">{{ item.like_count }}</span>
    {% csrf_token %}
</div>
{%  endif %}

2. 修改JavaScript代码

绑定所有点赞按钮的事件,修正请求逻辑:

// 遍历所有点赞按钮绑定事件
document.querySelectorAll('.likes').forEach(likeBtn => {
    likeBtn.addEventListener("click", (e) => {
        e.preventDefault();
        const postId = likeBtn.dataset.id;
        const likeCountEl = document.getElementById(`numOfLikes_${postId}`);
        // 获取CSRF令牌
        const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;

        fetch(`/likes/${postId}`, {
            credentials: "include",
            method: "POST",
            headers: {
                "Accept": "application/json",
                'X-CSRFToken': csrftoken
            },
            body: new FormData(e.target.closest('form')) // 直接提交整个表单的数据
        })
        .then(response => response.json()) // 用json()解析响应
        .then(result => {
            if (result.likeButton === 'Like'){
                likeBtn.innerHTML = "Unlike";
                likeBtn.value = "Unlike";
            } else {
                likeBtn.innerHTML = 'Like';
                likeBtn.value = "Like";
            }
            likeCountEl.innerHTML = result.total_likes;
        })
    })
})

3. 优化后端views.py代码

删除冗余查询:

@login_required
def likes(request, post_id):
    try:
        current_user = request.user
        post = Post.objects.get(id=post_id)
        total_likes = post.like_count
        likeButton = request.POST.get('buttonForLikes')
        if likeButton == 'Like':
            total_likes += 1
            post.like_count = total_likes
            post.like.add(current_user)        
        else:
            total_likes -= 1
            post.like_count = total_likes
            post.like.remove(current_user)
        post.save() # 只需保存一次即可
        return JsonResponse({'likeButton': likeButton, 'total_likes': total_likes}, status=200)
    except KeyError:
        return HttpResponseBadRequest("Like Error")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 11:06:02