Reputation:
This can easily be done with Ajax and Jquery, but this version of Django seems to be making it extra difficult. It requires the '{% csrf_token %}' (it'll throw an error without this) and that automatically submits the file when submit is pressed.
<form
id="data_upload"
method="POST"
enctype="multipart/form-data"
class="form-horizontal"
>
{% csrf_token %}
<div class="input-group mb-3">
<div class="custom-file">
<input
id="file_select"
type="file"
class="custom-file-input"
id="inputGroupFile02"
accept=".csv, .xslx"
name="file"
/>
<label
id="submit_label"
class="custom-file-label"
for="inputGroupFile02"
aria-describedby="inputGroupFileAddon02"
>Upload CSV or Excel file</label
>
</div>
<div class="input-group-append">
<button
id="upload_button"
type="submit"
class="input-group-text btn"
id="inputGroupFileAddon02"
disabled
>
Upload
</button>
</div>
</div>
<div class="d-flex justify-content-center">
<div
id="loading_div"
class="spinner-border"
role="status"
style="display: none;"
>
<span class="sr-only">Loading...</span>
</div>
</div>
</form>
Here's the ajax
$(document).ready(function () {
$("#data_upload").submit(function (event) {
event.preventDefault();
var fd = new FormData
fd.append('file', file_input[0].files[0])
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest()
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,
type: "POST",
data: fd,
processData: false,
contentType: false,
success: function (result) {
alert('WOOOO!')
},
});
});
});
urls.py
urlpatterns = [
path('upload', UploadView.as_view(), name="upload"),
]
View.py
class UploadView(TemplateView):
def get(self, request, *args, **kwargs):
return render(request, 'upload_datatable.html')
def post(self, request, *args, **kwargs):
uploaded_file = request.FILES['file']
uploaded_file_name = uploaded_file.name
if len(uploaded_file) != 0:
if uploaded_file_name.endswith('.csv'):
file_path = self.upload_csv_to_data(uploaded_file)
elif uploaded_file_name.endswith('xlsx'):
file_path = self.upload_excel(uploaded_file)
else:
return HttpResponse({'error': 'Not valid CSV or Excel'}, content_type="application/json",
status_code=400)
else:
return HttpResponse({'error': 'No Data'}, content_type="application/json", status_code=400)
def upload_csv_to_data(self, file):
id = str(uuid.uuid4())
with open(f'data/{id}.csv', 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return f'data/{id}'
def upload_excel_to_data(self, file):
id = str(uuid.uuid4())
with open(f'data/{id}.txt', 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return f'data/{id}'
def is_csv_file(self, file):
try:
dialect = csv.Sniffer().sniff(file.read(1024))
file.seek(0)
return True
except csv.Error:
return False
def is_excel_file(self, file):
try:
book = open_workbook(file)
return True
except XLRDError as e:
return False
So when I have preventDefault to stop Django from sending anything, but when I look at network, nothing is being sent and the "WOOOOO!" isn't being printed and my breakpoint in Django at the POST endpoint isn't be triggered. So I don't think the ajax is sending the file, but at the same time I'm getting no errors. Any advice?
Upvotes: 1
Views: 674
Reputation:
Even though no error was thrown when I removed
xhr: function () {
var xhr = new window.XMLHttpRequest()
xhr.upload.addEventListener("progress", progressHandler, false);
xhr.addEventListener("load", completeHandler, false);
xhr.addEventListener("error", errorHandler, false);
xhr.addEventListener("abort", abortHandler, false);
return xhr;
},
it started to work so yea.
Upvotes: 1
Reputation: 2909
Pass e.currentTarget
when instantiating a new FormData
object so you include the csrf_token
in the submitted info.
...
var fd = new FormData(event.currentTarget)
fd.append('file', file_input[0].files[0])
...
Upvotes: 0