javascript - FormData() 对象在 Django 后端始终为空

标签 javascript ajax django forms validation

我正在尝试通过 AJAX 上传 HTML 表单(只有 JS,没有 jQuery)。该表单是由我的模板通过添加三个组件来组装的:csrf token 、ModelForm 和常规 Django 表单 (forms.Form)。模型表单 {{ form.as_p}} 包含表单的可见部分,而表单 {{ order_form }} 包含一些隐藏字段。我的模板的表单部分如下所示:

<form id="{{ form_id }}" action="javascript:submitThisForm('{{ form_id }}', '/submit_blog_entry/')" method='POST' enctype='multipart/form-data'>
        {% csrf_token %}
        {{ form.as_p }}
        {{ other_form }}
        <input type='submit' value='SAVE changes' />
</form>

我已经尝试从 <form> 中删除 enctype标签(我在另一个问题的回复中读到 FormData() 自动添加了这个标签),但无济于事。

按下提交按钮时,将调用 JS 函数submitBlodEntryForm(),传递表单 ID 和用于 AJAX 请求的 url。该JS函数的代码在这里:

function submitThisForm(form_ID, url){

    var submit_form = document.getElementById(form_ID);
    var formData = new FormData(document.getElementById(form_ID));

    httpRequest = new XMLHttpRequest();

    if (!httpRequest){
        alert("Giving up, cannot create an XMLHTTP instance.");
        return false;
    };

    var url = "/submit_blog_entry/";
    var sendCSRFtoken = "csrfmiddlewaretoken="+String(getCookie('csrftoken'));
    var sendContent = sendCSRFtoken+"&"+formData;

    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('POST', url, true);
    httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    //httpRequest.send();

    httpRequest.send(sendContent);
    // alternatively: httpRequest.send(formData); 

}

AJAX 请求被提交到服务器(Django View )并由服务器接收。如果我不按照上面的 JS 代码(变量 sendContent)中所示手动添加 csrf token ,而只是发送 formData,则会收到 403 错误,显然是因为服务器找不到 token 。不过,它应该是表单的一部分......

当我尝试将接收到的数据绑定(bind)到相应的表单时,验证失败:

form = ThisForm(request.POST)
if form.is_valid():
    #do something

如果我打印 request.POST 中的内容,我会在终端中看到以下内容:

<QueryDict: {'[object FormData]': [''], 'csrfmiddlewaretoken': ['token goes here']}>

显然,FormData 对象是空的。我也这么认为,因为我的表单中的两个必填字段出现以下两个错误(通过使用 form.errors.as_data()):

[ValidationError(['This field is required.'])]

出了什么问题?我是否弄乱了模板,导致 FormData() 无法生成有用的数据?我是否错误地创建了 AJAX 请求?或者问题出在服务器端(尽管到目前为止我几乎没有做任何事情)?

谢谢,非常感谢您的帮助!

最佳答案

最好不要像这样将表单元素传递给 FormData:

new FormData(document.getElementById(form_ID))

我几乎可以肯定,它仅受 Firefox 支持。其他浏览器不会自动填充该对象。

还有你在哪里:

var sendContent = sendCSRFtoken+"&"+formData;

由于“sendCSRFtoken”是一个字符串,它会调用 formData 上的 toString() 方法并将两者连接起来,这就是为什么您在 django 端得到“[object FormData]”。

完成这项工作的一种方法是使用以下方法添加表单字段:

formData.append(name, value);

对 CRSF token 执行相同的操作,然后像这样调用 send:

httpRequest.send(formData);

XMLHttpRequest 有多个发送重载,因此如果您愿意,您也可以发送编码字符串:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#send()

在调试时,在 ajax 调用之前在 Chrome 开发者工具中打开网络选项卡以验证发布的内容是否正确,然后排除客户端之前,这将非常有帮助。

关于javascript - FormData() 对象在 Django 后端始终为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36391273/

相关文章:

javascript - @apollo/react-hooks 中的 `useSubscription` 方法加载卡住

javascript - 如何将输入文本作为参数传递给 javascript onblur 事件?

javascript - 在 RequireJS require 函数中处理先决条件加载失败

php - Ajax登录技术(后端php)

php - 如何为 Symfony3 上的 AJAX 调用添加 CSRF 保护?

javascript - Django 与谷歌图表

python - 在 Django 模板中使用外键作为变量

javascript - 从对象 Javascript 访问数据

php - 如何在 Ajax 响应中调用 Javascript?即 : Close a form div upon success

mysql - 如何使用 Django 处理数百个相同的数据库?