I am trying to use django-progressbarupload app
to add progress bar to my Django app. But it is not working .... The django-progressbarupload app
templates tags are loading fine and also file is uploading to the server but progress bar is not showing up ...and their is no javascript error on the console... I have followed this tutorial
Can anyone tell how to add progress bar to Django app
It clearly is a bug in webkit based browsers, here's the relevant thread:
Ajax form upload progress bar
Also here is the relevant github issue:
https://github.com/ouhouhsami/django-progressbarupload/issues/2
To comprehend, webkit doesn't allow to make ajax calls while uploading file, the usual workaround is to use dynamically created iframe (mentioned in above SO thread).
It's not the best solution (and not so consistent) but it will be the easiest to implement.
Create js file e.g. progress_bar.js
In your admin.py
class YouSuperModelAdmin(admin.ModelAdmin):
...
class Media:
js = ['/static/js/progress_bar.js']
...
In progress_bar.js
(function($){
$(function(){
$(document).ready(function() {
$( "#form_id" ).submit(function( event ) {
event.preventDefault();
var post_data = new FormData($("form")[0]);
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
var new_div = document.createElement('div');
new_div.innerHTML = '<progress id="progressBar" value="0" max="100" style="width:300px;"></progress><h3 id="status"></h3><p id="loaded_n_total"></p>';
document.getElementsByClassName('submit-row')[0].appendChild(new_div)
xhr.upload.addEventListener("progress", progressHandler, false);
xhr.addEventListener("load", completeHandler, false);
xhr.addEventListener("error", errorHandler, false);
xhr.addEventListener("abort", abortHandler, false);
return xhr;
},
url: window.location.href,// to allow add and edit
type: "POST",
data: post_data,
processData: false,
contentType: false,
success: function(result) {
window.location.replace("/admin/yourapp/yoursupermodel/");
}
});
});
});
});
})(django.jQuery);
The idea is to prevent default form submition, create new XMLHttpRequest, inject progressbar with messages and then send the data showing the process.
It is very important to set processData: false, contentType: false, otherwise it will not handle the file in the form
And finaly in your progress_bar.js set event handlers for the progress bar itself.
function _(el) {
return document.getElementById(el);
}
function progressHandler(event) {
_("loaded_n_total").innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
var percent = (event.loaded / event.total) * 100;
_("progressBar").value = Math.round(percent);
_("status").innerHTML = Math.round(percent) + "% uploaded... please wait";
}
function completeHandler(event) {
_("status").innerHTML = event.target.responseText;
_("progressBar").value = 0; //wil clear progress bar after successful upload
}
function errorHandler(event) {
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event) {
_("status").innerHTML = "Upload Aborted";
}
NOTE: In order not to have html page appearing under the form after success you have to change your view that returns HttpResponse object or simply change the window.location.
The described method should work for any form with django.