我正在尝试通过 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/