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
相关产品推荐
相关产品推荐

