如何用原生JavaScript异步提交POST表单?Django无法获取数据
解决Django后端无法获取原生JS异步POST表单数据的问题
我看了你的代码,问题主要出在异步请求发送的数据格式和请求头设置上,Django没法正确解析你直接发送的字符串值。下面一步步帮你修复:
1. 修复前端JS的请求数据格式
你现在直接把mail_input的value发送出去,Django不知道这个值对应的键是mail_input,而且没有明确告诉后端你发送的是表单编码数据。有两种简单的解决方式:
方式一:使用FormData对象(推荐,更简洁)
FormData会自动处理表单数据的编码,还能让浏览器自动设置正确的Content-Type请求头:
function send_mailform(){ var http = new XMLHttpRequest(); http.open("POST", "/index", true); // 设置CSRF Token http.setRequestHeader('X-CSRFToken', getCookie('csrftoken')); // 告诉后端这是AJAX请求(方便后端判断请求类型) http.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // 用FormData自动收集整个表单的数据 var formData = new FormData(document.getElementById("mail_form_id")); // 请求完成后的回调处理 http.onload = function() { if (this.status >= 200 && this.status < 400) { console.log("请求成功"); // 这里可以添加成功后的UI提示 } else { console.log("请求出错"); } }; http.send(formData); }
方式二:手动构造表单编码字符串
如果你不想用FormData,也可以自己拼接键值对,并手动设置Content-Type:
function send_mailform(){ var http = new XMLHttpRequest(); http.open("POST", "/index", true); http.setRequestHeader('X-CSRFToken', getCookie('csrftoken')); http.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // 必须设置这个请求头,Django才能识别表单编码的数据 http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 对输入值进行URL编码,避免特殊字符导致解析错误 var mail_input = encodeURIComponent(document.getElementById('mail_input').value); // 拼接成Django能识别的键值对格式:key=value var data = `mail_input=${mail_input}`; http.onload = function() { if (this.status >= 200 && this.status < 400) { console.log("请求成功"); } else { console.log("请求出错"); } }; http.send(data); }
2. 修复后端的AJAX判断逻辑
注意:request.is_ajax()在Django 3.1之后已经被废弃了,你应该通过请求头来判断是否是AJAX请求:
# views.py def index(request): # 替换原来的if request.is_ajax: if request.headers.get('X-Requested-With') == 'XMLHttpRequest': # 现在就能正确拿到mail_input的值了 print(request.POST.get('mail_input')) # 记得返回响应,比如JSON格式的结果 return JsonResponse({'status': 'success', 'message': '数据接收成功'}) # 其他非AJAX请求的逻辑...
额外优化:整合表单提交事件
你现在同时用了form.addEventListener('submit', handleForm)和按钮的onclick,其实可以把发送请求的逻辑直接放到submit事件处理里,避免重复绑定:
var form = document.getElementById("mail_form_id"); form.addEventListener('submit', function(event) { event.preventDefault(); // 阻止页面默认刷新 var http = new XMLHttpRequest(); http.open("POST", this.action, true); // 直接复用表单的action属性 http.setRequestHeader('X-CSRFToken', getCookie('csrftoken')); http.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); var formData = new FormData(this); // 直接用当前表单创建FormData http.onload = function() { if (this.status >= 200 && this.status < 400) { console.log("请求成功"); } else { console.log("请求出错"); } }; http.send(formData); });
这样就可以去掉按钮的onclick="send_mailform()"属性了,代码结构更简洁。
内容的提问来源于stack exchange,提问作者VicenteC
相关产品推荐
相关产品推荐

