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

如何解决Django动态页面POST请求仅返回最后一条数据问题

动态生成测验按钮仅传递最后一条数据的解决方案

问题根源

循环生成按钮时,事件绑定未为每个元素创建独立作用域,导致所有按钮的回调逻辑都引用了循环结束后的变量值(即最后一条测验数据);若使用内联onclick或重复表单控件,也会出现参数被覆盖的情况。


解决方法1:使用自定义数据属性+独立事件绑定(AJAX方式)

通过为每个按钮添加自定义data-*属性存储测验信息,再为每个按钮绑定独立的点击事件,确保点击时读取当前按钮对应的参数。

前端JS代码示例

// 辅助函数:获取Django所需的CSRF Token
function getCsrfToken() {
  return document.querySelector('[name=csrfmiddlewaretoken]').value;
}

// 假设quizzes是从API获取的测验数组
quizzes.forEach(quiz => {
  // 创建测验容器
  const quizDiv = document.createElement('div');
  quizDiv.className = 'quiz-item';
  
  // 测验标题
  const quizTitle = document.createElement('h3');
  quizTitle.textContent = quiz.quiz_name;
  
  // 创建Scan按钮
  const scanBtn = document.createElement('button');
  scanBtn.textContent = 'Scan';
  // 为按钮添加自定义数据属性,存储当前测验的ID和名称
  scanBtn.dataset.quizId = quiz.quiz_id;
  scanBtn.dataset.quizName = quiz.quiz_name;
  
  // 绑定独立点击事件
  scanBtn.addEventListener('click', function() {
    // 从当前按钮的自定义属性中读取参数
    const targetQuizId = this.dataset.quizId;
    const targetQuizName = this.dataset.quizName;
    
    // 发送POST请求到后端
    fetch('/scan/', {
      method: 'POST',
      headers: {
        'X-CSRFToken': getCsrfToken(),
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        quiz_id: targetQuizId,
        quiz_name: targetQuizName
      })
    })
    .then(res => res.json())
    .then(data => console.log('扫描触发成功:', data))
    .catch(err => console.error('请求失败:', err));
  });
  
  // 组装元素并添加到页面
  quizDiv.appendChild(quizTitle);
  quizDiv.appendChild(scanBtn);
  document.getElementById('quizzes-container').appendChild(quizDiv);
});

解决方法2:独立表单提交(同步请求方式)

为每个测验生成独立的表单,表单内的隐藏字段存储当前测验的参数,确保提交时传递对应的数据。

前端JS代码示例

function getCsrfToken() {
  return document.querySelector('[name=csrfmiddlewaretoken]').value;
}

quizzes.forEach(quiz => {
  // 创建独立表单
  const quizForm = document.createElement('form');
  quizForm.method = 'POST';
  quizForm.action = '/scan/';
  quizForm.className = 'quiz-form';
  
  // 添加CSRF Token隐藏字段
  const csrfInput = document.createElement('input');
  csrfInput.type = 'hidden';
  csrfInput.name = 'csrfmiddlewaretoken';
  csrfInput.value = getCsrfToken();
  
  // 添加quiz_id隐藏字段
  const idInput = document.createElement('input');
  idInput.type = 'hidden';
  idInput.name = 'quiz_id';
  idInput.value = quiz.quiz_id;
  
  // 添加quiz_name隐藏字段
  const nameInput = document.createElement('input');
  nameInput.type = 'hidden';
  nameInput.name = 'quiz_name';
  nameInput.value = quiz.quiz_name;
  
  // 创建提交按钮
  const submitBtn = document.createElement('button');
  submitBtn.type = 'submit';
  submitBtn.textContent = 'Scan';
  
  // 组装表单并添加到页面
  quizForm.appendChild(csrfInput);
  quizForm.appendChild(idInput);
  quizForm.appendChild(nameInput);
  quizForm.appendChild(submitBtn);
  document.getElementById('quizzes-container').appendChild(quizForm);
});

后端Django Views代码适配

确保后端能正确接收AJAX或表单提交的参数:

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt  # 若使用AJAX且未通过Cookie传递CSRF,需添加此装饰器;表单提交可移除
def scan_quiz(request):
    if request.method == 'POST':
        # 处理AJAX JSON请求
        if request.content_type == 'application/json':
            req_data = request.json()
            quiz_id = req_data.get('quiz_id')
            quiz_name = req_data.get('quiz_name')
        # 处理表单提交请求
        else:
            quiz_id = request.POST.get('quiz_id')
            quiz_name = request.POST.get('quiz_name')
        
        # 执行扫描脚本逻辑
        print(f"触发扫描:quiz_id={quiz_id}, quiz_name={quiz_name}")
        # 此处替换为你的扫描业务代码
        
        return JsonResponse({'status': 'success', 'msg': f"已开始扫描测验:{quiz_name}"})
    return JsonResponse({'status': 'error', 'msg': '仅支持POST请求'}, status=400)

验证方式

  1. 前端:点击不同按钮时,在浏览器控制台打印传递的quiz_id和quiz_name,确认与当前测验匹配。
  2. 后端:查看控制台日志,确认接收的参数与点击的测验对应。

内容的提问来源于stack exchange,提问作者Connor.Ryan-UC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:27:07