Continuously check if file exists with AJAX in Django - javascript

I've developed an application in Django where a user goes to a form on a site and enters in an Elasticsearch query, then generating a report for the user to download. It all works fine and dandy, but lately in testing some more queries we've noticed that some return a lot of results which leads to a timeout request.
What we've figured out that we'd like to do is have Django continuously check if a file exists (because it won't be written to the local system until it's completed) to prevent that timeout issue. Additionally, once the file is done being created we want to add a download button so that the user knows it is done.
Following this tutorial, I added a function to my views.py and associated it with a url which is then called by a javascript code block in my html form. Because I am brand new to using AJAX, JQuery, Javascript, and Django I'm not quite sure how to get it to work. Mainly, I'm trying to figure out how to get it to keep checking if the file is done being created yet. If this were just using basic Python I would do a while loop but I'm unclear how to translate that to JavaScript.
views.py
def check_progress(request):
"""
Returns whether document generation is complete or in progress
Returns 0 for in-progress, 1 for complete (either due to completion, or error)
"""
# check if file exists, return response as a JSON
file = "/report.docx"
data = {
"file_created": path.exists(file)
}
return JsonResponse(data)
urls.py
from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.get_query, name='form'),
path('^ajax/check_progress/$', views.check_progress, name='check_progress')
] + static(settings.STATIC_URL, document_root=settings.STAT)
form.html
{% block javascript %}
<script>
$("#id_username").change(function () {
var username = $(this).val();
$.ajax({
url: '/ajax/check_progress/',
type: 'HEAD',
data: {
'file_exists': 'True'
},
dataType: 'json',
success: function (data) {
if (data.exists) {
alert("This file is not yet created");
}
}
});
});
</script>
{% endblock %}

You can use setInterval to continually make requests to your backend to see if the file is complete. When it has finished the file, you clear the interval.
var checkInterval = setInterval(isFileComplete, 10000); //10000 is 10 seconds
function isFileComplete() {
$.ajax({
url: '/ajax/check_progress/',
type: 'HEAD',
data: {
'file_exists': 'True'
},
dataType: 'json',
success: function (data) {
if (data.exists) {
alert("This file is not yet created");
//add your own flag here to stop interval
clearInterval(checkInterval);
}
}
});
}

You can use setTimeout to run your Ajax request at regular intervals

Related

How my javascript can get json result returned by Flask Python route?

I have a flask web application with python.
I have a template where user have a list of tasks with checkboxes to enable or disable the task. I use jsonify and javascript to update or disable the value in Mysql database.
here is the route:
#app.route('/update_enable_task_user', methods=['GET', 'POST'])
#login_required
def update_enable_task_user():
print(f"update_enable_task_user request.form : {request.form}")
taskuser = TaskUser.query.filter_by(id=int(request.form['id_task_user'])).first()
print(f"request.form['enable'] : {request.form['enable']} - {type(request.form['enable'])}")
if request.form['enable'] == "1":
return jsonify({'result':'failed'})
else:
return jsonify({'result':'success'})
Here is the template:
<div id="enable_disable_task_2">
<label><input type="checkbox" onclick="checktaskuser()" class="ios-switch switch green" id="platform_task_2_enable" platform_id_task_user="2" name="platform_task_2_enable"
style="opacity: 0;"/>
<div>
<div></div>
</div>
</label>
</div>
function checktaskuser(){
var taskuser_update = document.getElementById("platform_task_{{task[5]}}_enable");
var url= window.location.href;
alert(taskuser_update);
if ( document.getElementById("platform_task_{{task[5]}}_enable").checked === false ) {
alert("platform_task_{{task[5]}}_enable is NOT checked!!!!");
var data;
$.ajax({
dataType: "json",
url: url,
data: data,
success: function (data) {
// begin accessing JSON data here
alert(result);
}
});
}
}
When My user check the checkbox, I see the 2 alert messages from javascript and I can see the json in network tab of browser console:
So for me, that means my flask python script did the job. But it failed somewhere in ajax?
But the 3rd alert in my javascript (alert(result);) is not showing up. I don't see any error messages (not in the Chrome console and not from the Flask console).
So I tried the getJSON function :
function checktaskuser(){
var taskuser_update = document.getElementById("platform_task_{{task[5]}}_enable");
var url= window.location.href;
alert(taskuser_update);
if ( document.getElementById("platform_task_{{task[5]}}_enable").checked === false ) {
alert("platform_task_{{task[5]}}_enable is NOT checked!!!!");
$.getJSON(
url ,
function(data) {
$('#result').textalert(data);
}
);
}
}
And I get same result: No 3rd alert and no error message.
EDIT 1:
After thinking of my issue, I think the javascript is executed before the FLask route is executed. That is why the json is empty as it was not sent yet by Flask route.
So my question is how my javascript can catch the json returned by FLask python route?
EDIT 2
I tried the solution of #folan
I get "Uncaught ReferenceError: data is not defined in console.
So my question is What is data? I am not an expert at all in jquery and javascript. I am trying to make work Python with javascript on a page which updata Mysql database without refreshing.
When user is on template page, he can update the column "enable" on Mysql DB without refreshing the page.
Flask update the Mysql DB on a special route.
#app.route('/update_enable_task_user', methods=['GET', 'POST'])
#login_required
def update_enable_task_user():
My new question is What is "data"?
It suppose to be the jsonify sent by Flask route which I caught. But Ajax seems not to catch the data in this solution.
I didn't declare it in my code and this $ajax() formula intrigues me.
So I read the doc
https://medium.com/coding-design/writing-better-ajax-8ee4a7fb95f
I didn't show the part of Flask code in template which call the flask route:
Jquery code & Flask to Update the column "enable" task in Mysql DB.
// ===================== TASK ENABLE WITH ID =================================
var platform_id_task_user = {{task[5]}};
// When user check the check box task_enable
$('#platform_task_{{task[5]}}_enable').on('change', function() {
// We collect the ID of task_user
// if task_enable is checked
if ($('#platform_task_{{task[5]}}_enable').is(':checked')){
var task_enable = 1;
}
// if task_enable is NOT checked
else{
var task_enable = 0;
}
// We send the data to our route update_enable_task_user
req = $.ajax({
url : '/update_enable_task_user',
type : 'POST',
data : {enable : task_enable,id_task_user: {{task[5]}}}
});
$('#enable_disable_task_{{task[5]}}').fadeOut(1000).fadeIn(1000);
});
In this code above, we can see the "data" variable. Maybe should I add my code here.
Instead of creating the function :
onclick="checktaskuser()"
Should I add my code here? I did try with an alert to display the "data" but I get again "Uncaught ReferenceError: data is not defined"
You can listen to your ajax request and on its completion, you can execute your success callback.
var call = $.ajax({
dataType: "json",
url: url,
data: data,
});
// Listening to completion
call.done(function(data){
alert(data);
});
You can read more about ajax https://medium.com/coding-design/writing-better-ajax-8ee4a7fb95f

An AJAX request to get the new upload URL

I'm using Google App Engine for a backend service and I'm trying to upload a file using an AJAX post and their Blobstore API. I got that part working. If you are not familiar with the service, is quite simple. Blobstore API uploads is a two step process: You need to get an upload url and then upload into that url.
Now, I'm implementing an editor, medium.com-like.
The thing is this plugin needs an endpoint for the upload. As my endpoint is not static and I need to update that URL each time, I have prepared an API in the backend that responds with a JSON file with that URL. I'm trying to do an AJAX request to get that URL but I'm getting an error, as the POST request is done to bad url.
This is the POST requet:
INFO 2014-10-19 08:58:22,355 module.py:659] default: "POST /admin/%5Bobject%20Object%5D HTTP/1.1" 200 2594
An this is my Javascript code:
function getURL(callback) {
return $.ajax({
type: "GET",
url: "/admin/upload_url",
dataType: "json",
success: callback
});
};
$('.editable').mediumInsert({
editor: editor,
addons: {
images: {
imagesUploadScript: getURL().done(function(json){return json['url']})
},
embeds: {
oembedProxy: 'http://medium.iframe.ly/api/oembed?iframe=1'
}
}
});
I guess I'm doing something wrong with the AJAX return, but if I console.log it I get the result I want. I've read this answer and try to apply it, but I didn't manage to get it working.
Thanks for your time and your help ! :)
If someone ever has the same problem this is the way I solved it. If you are reading this and you now a better one, please, every help is appreciated.
var url; // Set a global variable
// Define the AJAX call
function AJAXURL() {
return $.ajax({
type: "GET",
url: "/admin/upload_url",
success: function(response){
// Sets the global variable
url = response['url'];
}
});
};
// Gets a first upload URL doing an AJAX call while everything keeps loading
AJAXURL();
$('#editable').mediumInsert({
editor: editor,
addons: {
images: {
imagesUploadScript: function getURL() {
// makes a request to grab new url
AJAXURL();
// But returns the old url in the meanwhile
return url;
}
},
embeds: {
urlPlaceholder: 'YouTube or Vimeo Link to video',
oembedProxy: 'http://medium.iframe.ly/api/oembed?iframe=1'
}
}
});

400 Bad Request error when when moving application from local to web server

I have a pyramid application that runs perfectly on a local server, but when I move it over to a web server (Dreamhost), I get the following error:
400 Bad Request:
Bad request (GET and HEAD requests may not contain a request body)
The code in question is the following ajax in Javascript:
function summary_ajax(sName){
$.ajax({
type: "POST",
url: "summary",
dataType: "json",
data: {
'ccg_name': sName,
},
async: false,
success: function(data) {
//alert("In ajax success function") <----------- This never executes
lValues = data.lValues;
lLabels = data.lLabels;
},
});
};
return (lValues, lLabels);
And is handled in views.py:
#view_config(route_name="ccg_map_summary_ajax",renderer="json")
def ccg_map_summary_ajax(self):
sCCG = self.request.POST.get('ccg_name')
fData = open('pyramidapp/static/view_specific_js/ajax_summary_data.js')
dData = json.load(fData)
lLabels = dData[sCCG].keys()
lValues = dData[sCCG].values()
return {
'lLabels' : lLabels,
'lValues' : lValues,
}
I did some testing by placing alert() functions (its slow, because the server only reloads the script every so many minutes), and everything executes fine except for alerts in the ajax call. So it seems that either the post fails, or something goes wrong in the view. Any ideas?
So is there something in this code that works in my local server (in Pyramid) but breaks down in the web server (Dreamhost)?
The file structure is the same in the local and web server. I don't see why it shouldn't, but will fData still open the file for reading?
For anyone else out there, I found the problem:
The path I specified above was a relative path that worked on my system but not on the server because the working directories are obviously different. So instead of using a relative path, I just changed the script to have the correct absolute path.
To find the current working directory path, just enter pwd into terminal.

AJAX Post to store JSON with Python and javascript

I have been having problems with getting AJAX to post JSON correctly. The application is intended to be hosted on Google App Engine. But what I have does not post data.
Python
mainPage = """
<html>
html is included in my python file.
</html>
"""
class JSONInterface(webapp2.RequestHandler):
def post(self):
name =self.request.get('name')
nickname =self.request.get('nickname')
callback = self.request.get('callback')
if len(name) > 0 and len(nickname) >0:
newmsg = Entry(name=name, nickname=nickname)
newmsg.put()
if len(name)>0:
self.response.out.write(getJSONMessages(callback))
else:
self.response.out.write("something didnt work")
def get(self):
callback = self.request.get('callback')
self.response.out.write(getJSONMessages(callback))
This handler is meant to handle the Ajax calls from the web app. I am unsure if I need javascript to be associated with my main page in order to do so, as I haven't found information on it yet with my searches.
Javascript
$(document).ready( function() {
$("#post").bind('click', function(event){
var name = $("#name").val();
var nickname = $("#nickname").val();
postData = {name: name, nickname: nickname, callback: "newMessage"};
$.ajax({
type: "POST",
url: "http://localhost:27080/json",
data: postData,
dataType: "json",
done: function() {
// Clear out the posted message...
$("#nickname").val('');
},
fail: function(e) {
confirm("Error", e.message);
}
});
// prevent default posting of form (since we're making an Ajax call)...
event.preventDefault();
});
The Javascript for the post
Can someone advise me on how I could resolve the problem I am having. Thanks for the time and help.
Did you ask the same question yesterday and then delete it? I swear I just answered the same question.
You're not sending your data as a JSON string. If you want to send as JSON, you need to encode data as a JSON string, or else you're just sending it as a query string.
data: JSON.stringify(postdata),
HOWERVER, your request handler is actually processing the request properly as query string instead of JSON, so you probably don't want to do that.
For starters, the ajax call is pretty close. The full path
"http:://localhost:27080/json"
is not necessary, the relative path will work, but that is not the problem.
Your callback, as it stands, will work as 'success':
success: function(response) {
alert(response);
// Clear out the posted message...
$("#nickname").val('');
}
However, this callback is being phased out in favor of other methods. 'Done' should be chained like so:
$.ajax({
type: "POST",
url: "/json",
data: postData,
dataType: "json"
}).done(function(data){
console.log(data);
});
Also, there might be problems on the server. If you use some logging, you will see that the data is indeed being sent to the server.
import json ## we'll get to this below
import logging
class JSONInterface(webapp2.RequestHandler):
def post(self):
name = self.request.get('name')
logging.info(name) ## will print the value of 'name'
Unless your python function getJSONMessages(callback) is returning a json object, your callback will not be called, even after you add the response parameter.
In your python code:
import json
import logging
class JSONInterface(webapp2.RequestHandler):
def post(self):
callback = self.request.get('callback')
logging.info(callback) # will print correctly
self.response.out.write(json.dumps(callback))
Using the json.dumps method encodes the passing object to json, which is what your ajax object is looking for.

How to get content type of a given url inside Javascript?

I want to know the content type of a given url input by the user inside my Javascript code. Actually, I have a drop-down list (html,csv,xls etc.) and I want to make it so when the user inputs an url, I want to detect the type of the content of the url and based on this type I want to set the value of my drop-down list (html,csv,xls etc.). I know, I can get the content type using Ruby like this :
require 'open-uri'
str = open('http://example.com')
str.content_type #=> "text/html"
or, also, I could use curl to get the content and then parse it to know the content type. But, I need to do this inside my Javascript code because of my need explained above. Any thought ?
EDIT_1 :
I tried this code in my javascript :
$("#wiki_form_url").change(function(){
$.ajax({
type: "GET",
url: "content.rb",
data: {
// input_url: $("#wiki_form_url").val()
},
dataType: "html"
}).done(function (data) {
// `data` contains the content-type
alert('Success !!!');
}).fail(function () {
alert("failed AJAX call");
});
});
I have a ruby script content.rb inside which I do :
require 'open-uri'
str = open('http://www.ofdp.org/benchmark_indices/25')
str.content_type
But, it does not seem to work. I am getting Ajax failure. May be it's because of url path of the script content.rb ? How should I specify a script path here ? (Relative or absolute)
The same origin policy prevents you from using client side JavaScript to directly discover information about arbitrary URIs (URIs you control are a different story).
You'll need to get that information with another technology, such as your server side Ruby.
You could do this by simply submitting a form to the server and returning a new webpage to the browser.
If you don't want to leave the page, then you can pass the data using Ajax. There are no shortage of Ajax tutorials out there, here is a good one from MDN.
Here's an example of an AJAX call:
$(document).ready(function () {
$("#button_check").on("click", function () {
$.ajax({
type: "GET",
url: "Your URL",
data: {
input_url: $("#textbox_id").val()
},
dataType: "html"
}).done(function (data) {
// `data` contains the content-type
alert(data);
}).fail(function () {
alert("failed AJAX call");
});
});
});
Where your HTML is something like:
<input type="text" id="textbox_id" />
<input type="button" id="button_check" value="Submit" />
And your Ruby code would be something like:
require 'open-uri'
class TestController < ApplicationController
def index
req = open(params[:input_url])
render :text => req.content_type
end
end
I have never used RoR before, so I have no idea if this is right or works in the slightest. But it's what I could quickly conjure up when scrambling through several tutorials. It's simply the concept you seem to be looking for. You'll need to figure out how to map a URL to this method, and then update the AJAX option url to use that.
So in the Javascript code - in the done method, that means the whole AJAX request was successful and the data variable should contain the result from the Ruby code req.content_type.
Atlast I could figure out the whole thing with the great help of #Ian. Here is my completed code : In javascript file :
$("#wiki_form_url").change(function () {
$.ajax({
type: "GET",
url: "/wiki_forms/content",
data: {
input_url: $("#wiki_form_url").val()
},
dataType: "text"
}).done(function (data) {
// `data` contains the content-type
alert('Success');
console.log(data);
// alert(data);
}).fail(function () {
alert("failed AJAX call");
});
});
Inside my wiki_forms controller I created a new method named content :
def content
req = open(params[:input_url])
render :text => req.content_type
end
Then added a new route in routes.rb file :
get "/wiki_forms/content" => 'wiki_forms#content'
and used /wiki_forms/content as the ajax request url. And, everything is working nicely now.

Categories