如何解决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)
验证方式
- 前端:点击不同按钮时,在浏览器控制台打印传递的
quiz_id和quiz_name,确认与当前测验匹配。 - 后端:查看控制台日志,确认接收的参数与点击的测验对应。
内容的提问来源于stack exchange,提问作者Connor.Ryan-UC
相关产品推荐
相关产品推荐

