Ajax call to Python script. What am I missing? - javascript

What am I doing wrong here please. I want to run an very basic python script on the server side and the get the return value to the client side (ie javascript)
My python script is:
// Hello.py
--------------------------
import sys
def hello(str):
print('Hello ' + str)
return 1
if __name__ == '__main__':
hello(*sys.argv[1:])
and my Ajax call:
function getAjax(url, data){
return $.ajax({
type: 'POST',
url : url,
data: data,
success: function(response) {
return response;
}
});
}
getAjax("./scripts/hello.py", 'John').done(function(response){
console.log(response);
});
When I run getAjax the console.log(response) statement just prints the text (ie code) in my Python script. What is the step I am missing here please?

You need a server for link an http request from your browser on a specific port (default 80) of your network target and get the reponse of a specific script, the most simple usage for local tests like this in python is to use something like simplehttpserver: https://docs.python.org/2/library/simplehttpserver.html

Related

How to pass data to python scripts from JavaScript?

Here is the HTML file where in scripts portion I made an ajax request to pass some string to python function.
var status = "hello there!!!"
$.ajax({
url: "../SCRIPTS/cond.py",
type: 'POST',
data: {
'status': status
},
success: function (data) {
location.reload(true)
}
});
Here in url I set the path of python scripts. Python file where I want to fetch the requested data from JS and print it.
def main():
#
if __name__ == "__main__":
main()
def test(request):
print(request)
Note: Here I am not using any framework. Just pure HTML, JS and Python file.
Your backend logic(python script in this case) must be hosted on a http server. An "ajax" request is an http request. You can not POST something to a file on the local file system. Are you running your script on a server? If so, you should be able to access it via a http(s):// type URL.

Flask Ajax return multiple statuses before execution

I've got a web front-end for a flask app that is doing some heavy calculations on the back-end before passing the calculated data via JSON to the front-end to get charted.
The issue is, the calculation takes several minutes, and ideally I want the front-end to know the % done and status of the request rather than sitting there quietly.
JS Ajax request front-end:
function runBacktest() {
$.ajax({
type: "POST",
url: '/backtest',
data: {
run_partial: 1,
use_saved_model: false,
saved_model_file: 'model.h5'
},
dataType: "json",
success: function(data) {
//Successful data
},
error: function () {
alert('There was a problem contacting the server.');
}
});
}
Python backend:
#webapp.route('/backtest', methods=['POST'])
def backtest():
print('> Running Backtest...')
"""Calculation code goes on here"""
print('Percent Completed: \r{0:.1f}%'.format(round(pct_done,1)), end='')
"""Serialise each agent instance into a dictionary and put in list to be converted to JSON object"""
agents_serialised = [agent.__dict__ for agent in bt_engine.agents]
return json.dumps(agents_serialised)
Question is, how can I pass something like the percentage done, which I'm printing on stdout, on every change of percentage, to the front end? Followed by then passing the json data once it's finished?
A more Flasky approach would be to pass a generator to the response. From what I've read, this is the preferred approach to streaming data with Flask. Here's a very abstract example. Look here for my answer to different question where I have a more fleshed out and tested script using a generator in a response.
def do_calcs():
while(more_calculations):
"""do your calculations and figure out the percentage."""
agents_serialized = [agent.__dict__ for agent in bt_engine.agents]
yield json.dumps({percent: percent, agents: agents_serialized})
And in your route:
return Response(do_calcs(), mimetype='text/json')
For updating the percentage kind of stuff we need socket connection between Front end and Back end .Flask have a great package do this which is socket.io. And there is javascript support also for the socket.io.
Blog post which help to build this
I am sure you can build with this, because i done it before.
Sample Python code:
from flask import Flask, render_template
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('my percentage event', namespace='/test')
def test_message(message):
#create pertage opertion here
emit('percentage status', {'data': message['data']}, broadcast=True)
Sample javascript code:
$(document).ready(function(){
var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');
socket.on('percentage status', function(msg) {
//portion for update the percentage
});
});
These code are not exactly, But you can use as reference.

Passing a string from Python to Javascript

I'm trying to pass a string from Python to Javascript via ajax POST request but i'm finding serious difficulties.
I've tried both with and without using JSON.
Here's the code
JAVASCRIPT
$.ajax({
url: url, #url of the python server and file
type: "POST",
data: {'data1': "hey"},
success: function (response) {
console.log(" response ----> "+JSON.parse(response));
console.log(" response no JSON ---> " +response);
},
error: function (xhr, errmsg, err) {
console.log("errmsg");
}
});
Python
import json
print "Access-Control-Allow-Origin: *";
if form.getvalue("data1") == "hey":
out = {'key': 'value', 'key2': 4}
print json.dumps(out)
Result is a empty JSON. when i do something like JSON.parse in javascript I get a unexpected end of input error, and when i try to get the length of the response data the size I get is 0.
I suppose that there should be some problems with the client server communication (I use a CGIHTTPServer) or maybe something wrong with the datatype that python or javascript expects.
I also tried without JSON, with something like
Python
print "heyyyyy"
Javascript
alert(response) //case of success
but I also got an empty string.
Could you please give me some advices for handling this problem ?
Thanks a lot!
You may want to compare the two snippets of code CGIHTTPRequestHandler run php or python script in python and http://uthcode.blogspot.com/2009/03/simple-cgihttpserver-and-client-in.html.
There isn't enough code to tell where your request handling code is but if it's in a class inheriting from CGIHTTPRequestHandler then you need to use self.wfile.write(json.dumps(out)), etc.
I managed to solve the problem using the method HTTPResponse from the Django Framework.
Now it's something very similar to this
PYTHON (answering the client with a JSON)
from django.http import HttpResponse
...
data = {}
data['key1'] = 'value1'
data['key2'] = 'value2'
.....
response = HttpResponse(json.dumps(data), content_type = "application/json")
print response;
JAVASCRIPT (Retireving and reading JSON)
success(response)
alert(JSON.stringify(response));
Or if I just want to send a String or an integer without JSON
PYTHON (no JSON)
response = HttpResponse("ayyyyy", content_type="text/plain")
print response
JAVASCRIPT (Retrieving String or value)
success: function (response) {
alert(response);
This works very good, and it's very readable and simple in my opinion!
Instead of print json.dumps(out) you should use return json.dumps(out)
The print will only display it in python's console, just as console in javascript.

JSON passed from Python (Flask) into JavaScript is displaying on screen

I am passing a JSON from a Python back-end into my front-end JavaScript where I'm running a webGL (three.js) animation. The JSON holds numerical values that determine what happens in the animation. My problem is that while I have a basic ajax request working, the JSON is being printed to the screen (in lieu of the animation) rather than becoming a variable I can iterate through to control aspects of the animation. The two halves of the call are shown below.
I asked a related question to this one before and got some great help, but am obviously still missing a piece of the puzzle. I've been reading docs and all sorts of sources, yet need a nudge in the right direction to finally get this working. Any help is appreciated!
In the python backend:
from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list
#app.route('/')
def index():
motifs = get_motif_list(10)
# The first version of the return below successfully sends data, yet it is printed to the
# screen, rather than being stored as data in a variable.
return Response(json.dumps(motifs), mimetype='application/json')
# This version of the return does not work:
# return render_template("index.html", motifs = motifs)
In the JavaScript (note that the console.log sanity checks don't work - I have no idea why:
function foo() {
var array_data;
$.ajax({
type: "GET",
url: "/",
dataType: "json"
});
request.done(function(JSON_array) {
array_data = JSON.parse(JSON_array)["array"]
console.log(array_data); // sanity check - doesn't work
});
return array_data;
};
var array = foo();
console.log(array); // sanity check - doesn't work
UPDATE
With help from the advice below, I'm pretty close to having this off the ground. The JSON is no longer printing to the screen (an issue caused by the Flask return), and I've solved a multifunction callback issue I discovered along the way. However, I am now getting a parsererror from the complete textStatus. I think the problem now lays in the Python/Flask (see current code below). Thanks again for all who've helped!
Python/Flask (I think the problem is here - I'm a noob to Flask):
from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list
#app.route('/')
def index():
motifs = get_motif_list(10)
return Response(json.dumps(motifs), mimetype='application/json')
#app.route("/")
def index():
return render_template("index.html")
The JavaScript (the data is returned by the Deferred object - used to solve a callback issue):
function getData() {
var deferredData = new jQuery.Deferred();
$.ajax({
type: "GET",
url: "/",
dataType: "json",
success: deferredData.resolve(),
complete : function(xhr, textStatus) {
console.log("AJAX REquest complete -> ", xhr, " -> ", textStatus)}
});
return deferredData; // contains the passed data
};
It turns out I had a lot of problems in my code above, several of which I had to debug in related questions here and here.
Among them were:
in my original Flask index() function, it was dumping the JSON data to the screen because I was not rendering the index.html template anywhere.
I had matching routes ('/') and function names (index()) in the Flask functions
As mentioned in the comments I did an unnecessary double parsing of the JSON with dataType: json and array_data = JSON.parse(JSON_array)
the return from this asynchonous function always came up undefined because it was referenced before the call had resolved
in my later update to a Deferred object, the success property should have read: success: function(data) { deferredData.resolve(data);}
So, after all those fixes, here is the functioning code!
Flask/Python:
from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list
#app.route('/ajax')
def ajax() :
motifs = get_motif_list(10)
return Response(json.dumps(motifs), mimetype='application/json')
#app.route("/")
def index():
return render_template("index.html")
JavaScript: (note: this is the foo() function in my question above)
function getData() {
var deferredData = new jQuery.Deferred();
$.ajax({
type: "GET",
url: "/ajax",
dataType: "json",
success: function(data) {
deferredData.resolve(data);
},
complete: function(xhr, textStatus) {
console.log("AJAX Request complete -> ", xhr, " -> ", textStatus);
}
});
return deferredData; // contains the passed data
};
// I used the Deferred structure below because I later added Deferred objects from other asynchronous functions to the `.when`
var dataDeferred = getData();
$.when( dataDeferred ).done( function( data ) {
console.log("The data is: " + data);
});
In your javascript:
function foo() {
var array_data;
$.ajax({
type: "GET",
url: "/",
dataType: "json"
});
request.done(function(JSON_array) {
/*JSON_array is already parsed and it is an object..*/
array_data = JSON.parse(JSON_array)["array"]
/* ^ I belive you dont have to do this ^*/
console.log(array_data);
/* ^ change this to console.log(JSON_array);*/
});
return array_data;
/* ^ change this to return JSON_array;*/
};

Handle JSON events in Python

i have searched in google and on stackoverflow and could find a good answer.
i have that code on my HTML page that gets HTML output of python(i'm using jquery):
$.ajax({
type: "POST",
url: "getHTML.py",
success: function(response)
{
$('body').append(response);
}
});
python file looks like that:
baseHTML = "www.google.com"
user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
headers = {"User-Agent": user_agent}
req = urllib2.Request(baseHTML, headers=headers)
forumHTML = urllib2.urlopen(req)
page = Soup(forumHTML)
for e in page.findAll('script'):
e.extract()
print 'Content-Type: text/plain\r'
print '\r'
print page
Every thing works and i'm happy, But... now i tried to add another JSON that sent by a button click event:
$('#GetByURL_button').on("click", function(){
$.ajax({
url: "getHTML.py",
type: "POST",
data: JSON.stringify({"newURL": "www.stackoverflow.com"),
dataType: "json",
success: function(response) {
alert(response);
}
});
});
and now i just don't know how to handle that event in python.
So just to be clear - i want python to have something like:
if user didn't ask for anything(via JSON) load default page,
if user asked for "stackoverflow"(via JSON) load www.stackoverflow.com
if user asked for "dog" load www.DogsAreCool.com.
tnx for the help :)
You didn't specify what framework or mechanism you're using to hook up Python scripts, and your sample doesn't show the script handling input at all.
So, let's assume you're using a mechanism that gives you the request body as stdin, like old-school CGI. You'd do something like this:
content = sys.stdin.read()
data = json.loads(content)
newURL = data.get('newURL')
if newURL == 'dog':
newURL = 'http://www.DogsAreCool.com'
elif not newURL:
newURL = defaultPageURL
response = urllib2.urlopen(newURL)
# ...
Two approaches:
your server send backs the correct URL via a normal http response (200 OK)
your ajax code sets window.location
your browser is happy to redirect
Second one:
your server sends a redirect response with correct location header.
your ajax request will follow the redirect and return the correct content.
your ajax inserts content in the DOM.

Categories

Resources