Django后端

时间:2016-04-03 21:13:58

标签: javascript ajax django forms validation

我正在尝试通过AJAX上传HTML表单(只是JS,没有jQuery)。表单由我的模板通过添加三个组件来组装: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请求的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视图)。如果我没有手动添加csrf令牌,如上面的JS代码(变量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请求?或者是服务器端的问题(虽然到目前为止我几乎没有做任何事情)?

谢谢,非常感谢任何帮助!

3 个答案:

答案 0 :(得分:0)

你有2个问题

  • 您必须使用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);
...

答案 1 :(得分:0)

最好不要将表单元素传递给FormData,如下所示:

new FormData(document.getElementById(form_ID))

我几乎可以肯定,它只受到firefox的支持。其他浏览器不会自动填充对象。

您也可以这样做:

var sendContent = sendCSRFtoken+"&"+formData;

因为&#39; sendCSRFtoken&#39;是一个字符串,它调用formData上的toString()方法并连接这两个,这就是为什么你得到&#39; [object FormData]&#39;在django一侧。

使用此功能的一种方法是使用以下方法添加表单字段:

formData.append(name, value);

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

httpRequest.send(formData);

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

在进行调试之前,在ajax调用之前在chrome开发人员工具中打开网络选项卡,以便在排除客户端之前验证发布的内容是否正确,这将非常有用。

答案 2 :(得分:0)

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

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

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

再次感谢您的帮助!