Uploading files to django through ajax - javascript

I'm having trouble trying to upload files to django using ajax. The upload process is done in a modal.
Form
<div class="modal fade bs-example-modal-lg" id="fileUploadModal" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel2">Upload File</h4>
</div>
<div class="modal-body">
<div class="modal-body">
{% crispy fileform %}
</div>
</div>
</div>
</div>
</div>
The modal toggle
<a data-toggle="modal" href="#fileUploadModal" data-id="0" role="button" class="btn btn-success btn-sm pull-right">
<i class="fa fa-fw fa-cloud-upload"></i>
Upload File
</a>
This is how my file upload looks like
$(document).ready(function(){
var file = 0;
$('#fileUploadModal').on('show.bs.modal', function(e) {
file = $(e.relatedTarget).data('id');
var form = $(e.currentTarget).find('form');
$.ajax({
url: "{% url 'employee:ajax-file-upload' %}",
type: "POST",
data: $(form).serialize() + '&action=load&eid=' + employee + '&fid=' + file,
success: function(data) {
if (data['form_html']) {
$(form).html(data['form_html']);
$('.datepicker').datetimepicker({
format: 'YYYY-MM-DD'
});
}
}
});
});
$(".container" ).on('click', '#submit-file-upload', function(e) {
e.preventDefault();
e.stopImmediatePropagation();
var form = $(this).closest('form');
$.ajax({
url: "{% url 'employee:ajax-file-upload' %}",
type: "POST",
data: $(form).serialize() + '&eid=' + employee + '&fid=' + file,
success: function(data) {
if (!(data['success'])) {
$(form).replaceWith(data['form_html']);
$('.datepicker').datetimepicker({
format: 'YYYY-MM-DD'
});
}
else {
location.reload();
}
}
});
});
});
And my view looks like this
#json_view
#login_required
def ajax_file_upload(request):
if request.method == 'POST':
action = request.POST.get('action')
fid = int(request.POST.get('fid'))
eid = int(request.POST.get('eid'))
employee = Employee.objects.get(id=eid)
if action == 'load':
try:
file = File.objects.get(id=fid)
form = FileForm(instance=file)
except:
form = FileForm()
context = {}
context.update(csrf(request))
form_html = render_crispy_form(form, context=context)
return {'success': True, 'form_html': form_html}
else:
if fid == 0:
form = FileForm(request.POST or None, request.FILES or None)
else:
file = File.objects.get(id=fid)
form = FileForm(request.POST or None, request.FILES or None, instance=file)
if form.is_valid():
file = form.save(commit=False)
file.employee = employee
file.save()
messages.add_message(request, messages.SUCCESS, 'File was successfully saved.')
return {'success': True}
context = {}
context.update(csrf(request))
form_html = render_crispy_form(form, context=context)
return {'success': False, 'form_html': form_html}
I really can't seem to get it to work. I can successfully get other data but not the file. When I click on submit, it refreshes and I get a 'This field is required' in the file upload section.
I hope you can help me with this. Thanks.

Your ajax call is only posting the form data, not the file:
data: $(form).serialize() + '&action=load&eid=' + employee + '&fid=' + file
I would suggest using a library (such as jquery.fileupload.js but there's plenty of other options) to upload correctly a file, as it's quite a complex operation: you have to set the multipart/related body format, attach the file to your request as application/octet-stream, if it's large cut it into chunks etc etc...
With jquery.fileupload for example, uploading the file is as simple as:
$(function() {$('#fileupload').fileupload({
dataType: 'json',
formData: $(form).serialize()...
done: function(e, data) {
... your success handling code ...
}
});});
where $('#fileupload') targets your file input field (<input type='file'>).
The django code looks fine at first glance.

Related

How to popup form after file upload

File upload button on one file and popup form in another file("/uploadFile").
I want to popup form after upload file submit/on "ok" click.
This is my first file index.html where I have list that have upload file button:
<li><a href="/uploadFile"><input type="file" id="hiddenUploadField" style="display: none;" accept=".dxf, .dwg"
class="upload" data-toggle="modal" data-target="#importData">
<label for="hiddenUploadField"><i class="fas fa-folder-open"></i> <span>Import</span></label></a>
</li>
At the end of file I use this code for popup modal:
<div class="modal fade text-center" id="importData" >
<div class="modal-dialog modal-lg">
<div class="modal-content">
</div>
</div>
The code to trigger the popup is:
$('#hiddenUploadField').change(function (e) {
var node = $('#appBuckets').jstree(true).get_selected(true)[0];
var _this = this;
if (_this.files.length == 0) return;
var file = _this.files[0];
switch (node.type) {
case 'bucket':
var formData = new FormData();
formData.append('fileToUpload', file);
formData.append('bucketKey', node.id);
$.ajax({
url: '/api/forge/oss/objects',
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
$('#appBuckets').jstree(true).refresh_node(node);
_this.value = '';
}
});
break;
}
$('#importData').modal('show').find('.modal-content').load($(this).attr('href'));
});
}
The problem is when I click "ok" on the file window, it does not show up the modal popup box. It just fades the background and does nothing.
Your code to show the modal is need to inside the change function, like this
$('#hiddenUploadField').change(function (e) {
// your code goes here for the modal.
$('#importData').modal('show').find('.modal-content').load($(this).attr('href')); }
});

Check data in Succes ajax function to reidrect to specific view

I am calling a javascript function on click which calls an action method that returns either a partial view or full view. I want to load partial view in a modal popup and if it is a full view, then just want to redirect it.
View
foreach(var productTemplate in Products)
{
Add New Product
}
<div class="modal fade" id="mymodel" role="dialog" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Shared Products</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body" id="mymodelbody">
</div>
</div>
</div>
<script>
var loadModal = function (productId, customerId) {
$.ajax({
type: 'GET',
url: '/NewProductTemplate/CreateNewProduct',
cache: false,
data: {
productId: productId,
customerId: customerId
},
dataType: 'html',
success: function (data) {;
$("#mymodelbody").html(data);
$("#mymodel").modal("show");
}
});
}
</script>
NewProductTemplateController code:
public ActionResult CreateNewProduct(Guid productId, Guid customerId)
{
var sharedProduct = _productTemplateService.GetSharedProducts(productId);
var _finalSharedProducts = (sharedProduct.Any(t => t.productId != productId));
if (_finalSharedProducts)
{
var sharedProdctTemplate = _productTemplateService.GetSharedProduct(productId);
return PartialView("_shared", new SharedModel
{
SharedProduct = sharedProdctTemplate
});
}
else
{
_productTemplateService.CreateNewProduct(productId);
return RedirectToAction("Details", "ProductTemplate");
}
}
Problem is that when controller returns a full view, it loads in a modal popup which I don't want. I just want to check the data in success function and decide whether to load modal for partial view OR redirect to a full view. I am not sure how to do it.
Can please someone help me here? Thank you!
UPDATE:
I was able to make it work like
if (data.indexOf('<!DOCTYPE html>') != 0) {
$("#mymodelbody").html(data);
$("#mymodel").modal("show");
} else {
window.location.href = '/ProductTemplate/Details?productTemplateId=' + productId;
}
One more question:
Is there any way that I can create a ProductModal object in javascript and pass it to the Details action method of ProductTemplate?
If your action returns your whole page, it will include the <!DOCTYPE html> and <html> tags. You can check if the result starts with '<!DOCTYPE html>' for example to make to check if it is the whole page or not.
success: function (data) {
if (!data.startsWith('<!DOCTYPE html>')) {
$("#mymodelbody").html(data);
$("#mymodel").modal("show");
} else {
window.location.href = '<redirect url here>';
}
}

Rails: don't refresh page after modal action/submit

I have a modal which opens on top of another screen. The base screen has a filter method that uses AJAX to filter the results on that page.
After, I filter the results on the screen, I can open the modal and perform an action on the form in the modal. However, I don't want to perform a redirect/refresh.
How do I do this while still performing the submission?
My modal link is like:
<%= link_to this_path(user_id: user.id), class:"modal-link", data: {"modal-url" => this_path(user_id: user.id)} do %><span><i class="fa fa-plus"></i><% end %>
The modal is standard enough:
<div class="modal form-modal">
<div class="modal-container">
<div class="modal-dialog modal-dialog-wide">
<button class="close">×</button>
<div class="modal-content">
<div class="modal-header">
<h2 class="hdg-b">Edit This</h2>
</div>
<div class="modal-body">
<div id="error_explanation"></div>
<%= render 'form', form_path: action_path, form_method: :put, create: false %>
</div>
</div>
</div>
</div>
</div>
The AJAX is too:
MyProject.onPageLoad(function() {
var form = $('.edit_site_scope'),
onSubmit = function(event) { //callback handler for form submit
event.preventDefault();
var form = $(this),
url = form.attr("action"), //get form action:
type = form.attr("method"),
data = form.serialize();
var location = window.location.href;
var posting = $.ajax({
type: type,
url: url,
data: data,
dayaType: "json",
success:function(data, textStatus, jqXHR)
{
$('.modal').remove();
window.location = location;
$('#contact-tab-submit').show();
},
error: function(jqXHR, textStatus, errorThrown)
{
$('#error_explanation').html('');
errors = jqXHR.responseJSON;
$.each( errors, function( key, value ) {
$('#error_explanation').append('<div class="alert alert-dismissable" id="alert-message"><i class="fa fa-exclamation-triangle"></i>' + value + '<div class="alert-close">Close</div></div>');
});
$('#contact-tab-submit').show();
}
});
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){
$(this).remove();
});
}, 5000);
return false; // prevent default when submit button clicked
};
if (form.size() !== 0) {
form.submit(onSubmit);
}
});
And here is my controller action on the form submit:
def action_to_be_performed
#this_thing = ThisThing.where(id: params[:id]).first
#this_thing.update(this_things_params)
flash[:success] = "Successfully performed the action."
render json: #this_thing
rescue => error
Rails.logger.error "Exception caught updating this.\nCause: #{error}\n" + error.backtrace.join("\n")
render json: #this_thing.errors.full_messages, status: :bad_request
end
I really struggle with modals still and I guess with AJAX. How do I perform my action, close the modal and keep the current page open?
I figured out a simple solution on the drive home. The following line in my Javascript:
window.location = location;
can be changed to:
window.location.reload();

How to show Ajax response as modal popup

I have a link on clicking it is sending ajax request and getting response successfully which is html file and I am appending to a div, but I need to show that div as modal popup and I tried something below.
in html file
<a th:if="${ratingSummary}" href="#" class="small dark account review_ratings_login">Login to write a review</a>
<div id="login_for_review" data-toggle="modal" data-target="#reviewLoginModal"></div>
in js file
$(document).on('click', '.review_ratings_login', function () {
var $data = $('#review_product_id span').text();
var url = '/mycompany/login/'+$data;
$.ajax({
type: 'GET',
url: url,
success: function (output) {
$('#login_for_review').html(output).modal('show');// I tried to show this response as modal popup
},
error: function(output){
alert("fail");
}
});
});
output file
<div class="centerForm modal fade" role="dialog" style="margin-left: 35%;" id="reviewLoginModal">
<div class="modal-dialog modal-sm" >
<div class="modal-content">
// here I have login form
</div>
</div>
but I am not getting this html output as modal pup instead I am getting black screen can anyone help me how to do this?
In Bootsrap modal popup, You can use plain way to show modal which don't need pre-defined modal div container . see at modal
For E.g
$.ajax({
url: "url",
type: 'POST',
dataType: "html",
data:{id:params},
success: function(data, status, xhr) {
if(data==""){
window.location.href="/";
}
else{
BootstrapDialog.show({
title: "Modal Tital",
message: function(dialogRef){
$mydata = $($.parseHTML(data));
return $mydata;
},
onshow: function(dialog){
// and css change if need, eg.
dialog.$modalHeader.css("float","none");
},
onshown:function(dialog)
{
// event after shown
},
onhide:function(dailog)
{
// event on hide
}
});
}
},
statusCode: {
401: function () {
alert("Your session has been expired");
}
}
});
I solved this problem by creating modal and by removing data-toggle and data-target and just appending response to that modal div
Code For modal div
<div id="login_for_review" class="modal hide" role="dialog">
</div>
Code For hyperlink
<a th:if="${ratingSummary}" href="#" class="small dark account review_ratings_login">Login to write a review</a>
Code For ajax call
$(document).on('click', '.review_ratings_login', function () {
var $data = $('#review_product_id span').text();
var url = '/mycompany/login/'+$data;
$.ajax({
type: 'GET',
url: url,
success: function (output) {
$('#login_for_review').html(output).modal('show');//now its working
},
error: function(output){
alert("fail");
}
});
});

Use AJAX to upload a file, process, and return a result to Javascript using Flask

I've figured out how to upload a file using AJAX and Flask such that the page doesn't refresh and the file is uploaded to the server in some specified directory.
In the Python method (upload()), I want to process the filename with some regex and return an array to the Javascript file.
Do I still return render_template(index.html), even if I'm trying to request an array?
HTML (index.html)
<form id="upload-file" role="form" action="sendQuestions" method="post" enctype="multipart/form-data">
<div class="modal-body">
<label for="file"><b>Upload packet here</b></label>
<input type="file" name="file">
<p class="help-block">Upload a .pdf or .docx file you want to read.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button id="upload-file-btn" type="button" class="btn btn-primary" data-dismiss="modal" value="Upload">Upload</button>
</div>
</form>
Javascript
$(function() {
$('#upload-file-btn').click(function() {
var form_data = new FormData($('#upload-file')[0]);
$.ajax({
type: 'POST',
url: '/uploadajax',
data: form_data,
contentType: false,
cache: false,
processData: false,
async: false,
success: function(data) {
console.log('Success!');
},
});
});
});
Python (Flask)
#app.route('/uploadajax', methods=['POST'])
def upload():
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return render_template('index.html')
I'm playing around with adding this AJAX call in the Javascript after the $.ajax{} part, but did I do it right? I'm not sure if I can call the same Python method twice in one Javascript function, or if there's an entirely better way to do this.
ajaxRequest = ajaxFunction()
ajax.onreadystatechange = function() {
if (ajaxRequest.readyState === 4) {
if (ajaxRequest.status === 200) {
alert(ajaxRequest.responseText) //I want the Python to put the array into this ajaxRequest.responseText variable, not sure how.
}
else
alert('Error with the XML request.')
}
}
ajaxRequest.open("GET", 'uploadajax', true);
ajaxRequest.send(null);
Any help? Thanks.
You don't say what you want to achieve (hide some div, scroll window ...), and that's a main problem. To sum what should be done :
Don't return
return render_template('index.html')
but fe. if you want to notify the user about the upload status, make status for this call like
return Response('OK')
or other status - NOTOK or something.
Then in the js :
success: function(data) {
console.log('Success!');
},
manipulate the response
if (data == 'OK') {
alert ('YAY, FILE UPLOADED');
};

Categories

Resources