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

如何用原生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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 22:47:49