Django后端FormData()对象总是空
我想通过AJAX(只是JS,没有jQuery)上传HTML表单。表单由我的模板通过添加三个组件组装而成:csrf标记,ModelForm和常规Django表单(forms.Form)。模型表单{{form.as_p}}包含表单的可见部分,而{{order_form}}表单包含一些隐藏的字段。我的模板的形式部分看起来是这样的:Django后端FormData()对象总是空
<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>
标签删除加密类型(我在另一个问题的答复读取FORMDATA()自动将此),但无济于事。
当按下submit按钮时,调用JS函数submitBlodEntryForm(),传递表单ID和url以用于AJAX请求。该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视图)。如果我没有手动添加上面的JS代码(变量sendContent)中显示的csrf标记并只发送formData,我会得到一个403错误,显然是因为服务器找不到标记。它应该是这样的形式,虽然部分...
当我接收到的数据绑定到相应的表单,验证失败:
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请求吗?或者是服务器端的问题(尽管目前我几乎没有做任何事情)?
谢谢任何帮助,非常感谢!
你有2个问题
- 你必须使用FormData.append将数据添加到使用FORMDATA的请求。
- FORMDATA对象使用在请求中的多部分/格式数据的内容类型(其被自动设置,并且正确地)
...
var url = "/submit_blog_entry/";
formData.append("csrfmiddlewaretoken",getCookie('csrftoken'));
httpRequest.onreadystatechange = alertContents;
httpRequest.open('POST', url, true);
//httpRequest.send();
httpRequest.send(formData);
...
这可能是更好的形式元件不传递给FORMDATA这样的:
new FormData(document.getElementById(form_ID))
我几乎可以肯定,它只支持firefox。其他浏览器不会自动填充对象。
也是你做的事:
var sendContent = sendCSRFtoken+"&"+formData;
由于“sendCSRFtoken”是一个字符串,它呼吁FORMDATA的toString()方法并连接了两下,就这就是为什么你会得到“[对象FORMDATA]” Django方面。
formData.append(name, value);
做同样的CRSF令牌,然后调用发送这样的:使这项工作使用添加表单字段
一种方式
httpRequest.send(formData);
的XMLHttpRequest具有发送多个重载所以你可以发送一个编码的字符串,如果你愿意的话:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#send()
这将是非常有用的,当调试时有网络选项卡在铬开放在排除客户端之前,在ajax调用前验证工具是否正确无误。
感谢大家。我现在发现这个问题,*复制&粘贴。创建AJAX请求的JS函数submitBlogEntryForm()很糟糕。设置httpRequest标头
httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
引起了矛盾的编码指令。我只是完全删除了这一行,并且还避免在我的模板中的表单标记中指定“enctype”,并将所有这些都由FormData()自动设置。现在它工作了!
再次感谢您的帮助!
谢谢。我也尝试过,现在再次按照您的代码片段中的建议。也不起作用。即使我创建一个空的FormData()对象而不传递一个表单并添加它,csrf标记也不会通过(403错误再次出现)。 –