XmlHttpRequest (I)
-
Front-End
Using XMLHttpRequest with Django - setting csrf token
GET request
Example below inform user about the "Sending..." state (interval between sending data and receiving answer from server), eventual error state or about no answer situation. The last situation, we could simulate by specifying a timeout in request and then, turning off the server, ajax call will trigger the onerror handler: "No response ...". By specifying a timeout with a non-numeric value or a negative number, we can simulate a server error (500).
<script>
function getXHR(){
var xhr = false;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else { //code for IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr;
}
function GetData() {
var milisec1 = Date.now();
// Instantiate XHR
xhr = getXHR();
if(!xhr) {
alert("Ajax is not supported by your browser!");
return;
}
// Handle Response from Server
xhr.onreadystatechange = function () {
if (xhr.readyState < 4)
document.getElementById('div1').innerHTML = "Sending...";
else if (xhr.readyState === 4) {
if (xhr.status == 200 && xhr.status < 300){
var milisec2 = Date.now();
var dt = (milisec2 - milisec1).toString();
document.getElementById('div1').innerHTML = xhr.responseText + " (" + dt + " milisec delay)";
}
else
document.getElementById('div1').innerHTML = "Error: " + xhr.status;
}
}
xhr.onerror = function() {
document.getElementById('div1').innerHTML = "Error: No response from server.";
}
// Send data to server
var timeout = document.getElementById('timeout').value;
xhr.open('GET', 'reply/?timeout='+timeout);
xhr.send(null);
}
window.onload=function(){
var button1 = document.getElementById('test1');
button1.onclick = GetData;
}
</script>
<html>
Server response:<div id="div1" style="height:1.5em; width:100%; border: 1px solid black;"></div>
<p>
<button id="test1" type="button" >Test</button>
<label>server delay:</label>
<input type="text" value="0" id="timeout" size="3"/>seconds
</p>
</html>
Server response:
seconds
POST request
For POST requests, in order to avoid "Forbidden (CSRF token missing or incorrect.)" / error 403 reply from Django, without using jquery, we could set csrf token for XMLHttp request in two ways:
- by including in template, after the tag:
"{% csrf_token %}"
which result in hidden variable:
<input type='hidden' name='csrfmiddlewaretoken' value='...' >/
that we read in javascript:
var csrf_token = document.getElementsByName("csrfmiddlewaretoken")[0].value;
or
- rendering csrf in views.py by:
from django.template.context_processors import csrf ... data.update(csrf(request)) return render(request, page_request, data)
which result in:
data['csrf_token']='...'
rendered in template that we read in javascript:
var csrf_token = "{{ csrf_token }}"
Finally we could set:
xhr.setRequestHeader("X-CSRFToken", csrf_token);
<script>
function PostData() {
// Instantiate XHR
xhr = getXHR();
if(!xhr) {
alert("Ajax is not supported by your browser!");
return;
}
// Handle Response from Server
xhr.onreadystatechange = function () {
if (xhr.readyState < 4)
document.getElementById('div2').innerHTML = "Sending...";
else if (xhr.readyState === 4) {
if (xhr.status == 200 && xhr.status < 300){
document.getElementById('div2').innerHTML = xhr.responseText ;
}
else
document.getElementById('div2').innerHTML = "Error: " + xhr.status;
}
}
xhr.onerror = function() {
document.getElementById('div2').innerHTML = "Error: No response from server.";
}
// Send data to server
xhr.open('POST', 'reply/');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//=========================================================================
/**** include {% csrf_token %} in template ****/
var csrf_token = document.getElementsByName("csrfmiddlewaretoken")[0].value;
/**** render csrf in views.py ****/
//var csrf_token = "{{ csrf_token }}"
xhr.setRequestHeader("X-CSRFToken", csrf_token );
//=========================================================================
jsonStr = JSON.stringify({"key1":"a","key2":"b"});
xhr.send('name=John&json='+jsonStr);
}
window.onload=function(){
var button2 = document.getElementById('test2');
button2.onclick = PostData;
}
</script>
<html>
Server response:<div id="div2" style="height:1.5em; width:100%; border: 1px solid black;"></div>
<p>
<button id="test2" type="button" >Test</button>
</p>
</html>
Server response:
POST - ing data and file(s) with FormData
<script>
function PostData2() {
//FileObject
var f = document.getElementById("file").files[0];
if(f==undefined){
alert("Choose a file, please!");
return;
}
var comment = document.getElementById("comment").value;
var fd = new FormData();
fd.append("fileToUpload", f);
fd.append("comment",comment)
// Instantiate XHR
xhr = getXHR();
if(!xhr) {
alert("Ajax is not supported by your browser!");
return;
}
// Handle Response from Server
xhr.onreadystatechange = function () {
if (xhr.readyState < 4)
document.getElementById('div3').innerHTML = "Sending...";
else if (xhr.readyState === 4) {
if (xhr.status == 200 && xhr.status < 300){
document.getElementById('div3').innerHTML = xhr.responseText ;
//reset form
document.getElementById("file").value = "";
document.getElementById("comment").value = "";
}
else
document.getElementById('div3').innerHTML = "Error: " + xhr.status;
}
}
xhr.onerror = function() {
document.getElementById('div3').innerHTML = "Error: No response from server.";
}
// Send data to server
xhr.open('POST', 'reply/');
//=========================================================================
/**** include in template ****/
var csrf_token = document.getElementsByName("csrfmiddlewaretoken")[0].value;
/**** render csrf in views.py ****/
//var csrf_token = "{{ csrf_token }}"
xhr.setRequestHeader("X-CSRFToken", csrf_token );
//=========================================================================
xhr.send(fd);
}
window.onload=function(){
var button3 = document.getElementById('test3');
button3.onclick = PostData2;
}
</script>
<html>
Server response:<div id="div3" style="height:1.5em; width:100%; border: 1px solid black;"></div>
<p>
Comments: <input type="text" value="" id="comment" size="20"/>
File: <input type="file" id="file" name="files">
</p>
<p>
<button id="test3" type="button" >Test</button>
</p>
</html>
Server response:
Comments: File: