繁体   English   中英

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

[英]FormData() object is always empty in Django backend

我正在尝试通过AJAX(只是JS,没有jQuery)上传HTML表单。 通过添加三个组件,该模板由我的模板组装而成:csrf令牌,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请求的网址。 该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代码中所示的csrf令牌(变量sendContent),而只是发送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请求? 还是服务器端的问题(尽管到目前为止我几乎没有做任何事情)?

谢谢您的任何帮助,不胜感激!

你有两个问题

  • 您必须使用FormData.append将数据添加到使用Formdata的请求中。
  • FormData对象在请求中使用multipart / form-data内容类型(会自动正确设置)
...
var url = "/submit_blog_entry/";
formData.append("csrfmiddlewaretoken",getCookie('csrftoken'));

httpRequest.onreadystatechange = alertContents;
httpRequest.open('POST', url, true);
//httpRequest.send();

httpRequest.send(formData);
...

最好不要这样将form元素传递给FormData:

new FormData(document.getElementById(form_ID))

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

另外,您在哪里:

var sendContent = sendCSRFtoken+"&"+formData;

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

进行此工作的一种方法是使用以下方法添加表单字段:

formData.append(name, value);

对CRSF令牌执行相同的操作,然后按以下方式调用send:

httpRequest.send(formData);

XMLHttpRequest具有多个发送重载,因此您也可以根据需要发送编码的字符串: https : //developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#send()

在调试之前,在ajax调用之前先在chrome开发人员工具中打开“网络”标签,在排除客户端之前先验证发布的内容是否正确,这将非常有帮助。

感谢大家。 我现在发现了问题,愚蠢的复制和粘贴。 创建AJAX请求的JS函数SubmitBlogEntryForm()不好。 设置httpRequest标头

httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

导致矛盾的编码指令。 我只是完全删除了这一行,并且还避免在模板的form标记中指定“ enctype”,并将所有这些都由FormData()自动设置。 现在可以了!

再次感谢你的帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM