I am currently experimenting with uploading an HTML form through AJAX using pure JavaScript, without jQuery. The form is put together in my template by combining three components: the CSRF token, a ModelForm, and a regular Django form (forms.Form). The visible parts of the form are included in the model form {{ form.as_p}}, while the hidden fields are included in the form {{ order_form }}. This is how the form section looks in my template:
<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>
I attempted to remove enctype from the <form>
tag based on advice I found elsewhere that FormData() automatically includes it, but it didn't work.
Once the submit button is clicked, the JS function submitBlodEntryForm() is invoked, passing the form ID and the URL for the AJAX request. Here's the code for that JS function:
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("Unable to 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);
}
The AJAX request is sent to and received by the server (a Django view). If I don't manually include the CSRF token as shown in the JS code above (as sendContent) and just send formData, I get a 403 error, likely because the server can't find the token. However, it should be part of the form...
When I attempt to bind the received data to the corresponding form, the validation fails:
form = ThisForm(request.POST)
if form.is_valid():
#do something
If I check what's in request.POST, the Terminal shows:
<QueryDict: {'[object FormData]': [''], 'csrfmiddlewaretoken': ['token goes here']}>
It seems like the FormData object is empty. Additionally, I receive errors for two required fields in my form (using form.errors.as_data()):
[ValidationError(['This field is required.'])]
What could be causing this issue? Is there a problem with the template that prevents FormData() from generating useful data? Am I not setting up the AJAX request correctly? Or could the problem be on the server side (although minimal modifications have been made there so far)?
Your assistance is greatly appreciated. Thank you!