Ajax POST doesnt work / Twisted - javascript

Twisted.Web and AJAX
Similar thread already exits . I even took code from there , yet i have the same problem , the twisted server works like a charm, but can't figure out why i can't fetch it with ajax. In similar thread he says that alert comes out , but without data. For me even alert doesn't pop up , yet another ajax functions works , so in general with ajax is everything ok , but exactly with fetching something goes wrong.
As also said in similar thread i can fetch it with curl - $ curl --url http://localhost:8082/test -v , and it shows hello world , so servers works fine 100 % .
Any ideas ?
<script type="text/javascript">
// Submit button
$(function(){
$.ajax({type: "POST",
$('a').click(function(){
url: "http://localhost:8082/test",
data: {},
success: function(data) {alert("Success:" + data);}
});
});
});
</script>
<html>
[...]
Load Favorites Movies...
[...]
</html>
server.py
from twisted.web import server, resource, http
class RootResource(resource.Resource):
def __init__(self):
resource.Resource.__init__(self)
self.putChild('test', TestHandler())
class TestHandler(resource.Resource):
isLeaf = True
def __init__(self):
resource.Resource.__init__(self)
def render_GET(self, request):
return self.render_POST(request)
def render_POST(self, request):
return "hello world!"
if __name__ == "__main__":
import sys
from twisted.internet import reactor
reactor.listenTCP(8082, server.Site(RootResource()))
reactor.run()
Big thank you to Peter Le Bek and Darkporter.
Peter Le Bek asnwer marked as correct , and Darkporter vote up =) from me .
Answer : Peter's answer works out of the box , just the thing that confused me a little bit was the line , where you had to specify the static folder. It is easy ... just sepcify any folder there , put there index.html and it will a root directory , when you access it on the web.

Your javascript is mangled, try this:
wwwdir/index.html
<html>
<head>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
</head>
<body>
click me
<script type="text/javascript">
$('a').click(function(){
$.ajax({type: "POST",
url: "http://localhost:8082/test",
data: {},
success: function(data) { alert("Success: " + data); }
});
});
</script>
</body>
</html>
You'll probably still meet the cross-domain HTTP request restriction mentioned by darkporter, to solve this serve your webpage using the same Twisted server:
server.py
from twisted.web import server, resource, http, static
class TestHandler(resource.Resource):
isLeaf = True
def __init__(self):
resource.Resource.__init__(self)
def render_GET(self, request):
return self.render_POST(request)
def render_POST(self, request):
return "hello world!"
if __name__ == "__main__":
import sys
from twisted.internet import reactor
root = static.File('/path/to/wwwdir')
testHandler = TestHandler()
root.putChild('test', testHandler)
reactor.listenTCP(8082, server.Site(root))
reactor.run()

Is the page your JavaScript lives on served from the same host and port? If not you'll have a cross domain issue.

Related

How to communicate between python server and javascript client using AJAX and Flask?

I am following this tutorial to communicate between python and javascript. I am a beginner to this so I dont understand what exactly I am doing wrong.
Following is my code in index.html which sends a POST request to the python server side when the button is clicked:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript">
// setup some JSON to use
var cars = [
{ "make":"Porsche", "model":"911S" },
{ "make":"Mercedes-Benz", "model":"220SE" },
{ "make":"Jaguar","model": "Mark VII" }
];
window.onload = function() {
// setup the button click
document.getElementById("theButton").onclick = function() {
doWork()
};
}
function doWork() {
console.log("posting data")
// ajax the JSON to the server
$.post("receiver", cars, function(){
});
// stop link reloading the page
event.preventDefault();
}
</script>
This will send data using AJAX to Python:<br /><br />
<button type="button" id="theButton">Click Me!</button>
And this is my code on the python side:
import sys
from flask import Flask, render_template, request, redirect, Response
import random, json
app = Flask(__name__)
#app.route('/')
def output():
# serve index template
return render_template('index.html', name='Joe')
#app.route('/receiver', methods = ['GET', 'POST'])
def worker():
print("got some data")
# read json + reply
data = request.get_json()
result = ''
for item in data:
# loop over every row
result += str(item['make']) + ''
return result
if __name__ == '__main__':
app.run()
So, when I press the button in the index.html file, the tutorial says that I will be able to see a server response in the web browser. But even though my server is running, this is what I see in the network tab of developer tools for index.html in the Firefox web browser:
I don't understand what I am doing wrong and how I am supposed to see the communication between the client and server. Any help would be appreciated
Your request is not sending JSON, you have to stringify the cars object to send it as JSON.
function doWork() {
console.log("posting data")
// ajax the JSON to the server
$.post("receiver", JSON.stringify(cars), function(){
}, 'application/json');
// stop link reloading the page
event.preventDefault();
}
I also set the content type to application/json as this is required by request.get_json().
For your network tab issue, you have JS selected so you would not see ajax requests only javascript files. You have to have XHR selected or All.

How to handling response from Flask backend to run separated Python script?

Goal:
User inputs a personal token in the frontend which should get passed to a python script in the backend. The python script receives the token, places it correctly in it's code and executes. The scripts output should then be returned to the frontend.
I also want to keep the frontend and backend separated.
I've managed to pass information from the frontend to the backend and then received it back in my Chrome console.
Frontend is running at localhost:5500
Backend is running at localhost:5000
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<p>Insert Token: <input id="token">
<button id="send">Send</button>
<script src="app.js"></script>
</body>
</html>
app.js
$("document").ready(function(){
$("#send").click(function(){
var token = $("#token").val();
$.ajax({
url: "http://localhost:5000/token/",
type: "POST",
contentType: "application/json",
data: JSON.stringify({"token": token})
}).done(function(data) {
console.log(data);
});
});
});
views.py
from flask import Flask, request, jsonify
app = Flask(__name__)
#app.route('/token/', methods=['POST'])
def token_input():
response = request.get_json()
print(response)
return jsonify(response)
#app.after_request
def add_headers(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
return response
if __name__ == "__main__":
app.run(debug=True)
So far, my app gives me:
so_far
My guess is:
I have to make a new python script and wrap my script_that_uses_token.py in a function. Then import that function in views.py and somehow use that in the response..?

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.

What exactly does flask.abort() do?

I'm actually working with flask.
I use flask in order to run a server, which will be requested by a chrome extension (js).
Requesting the server from the extension is quite simple : I use the chrome.runtime.sendMessage() method. This method provides also a callback function, taking as parameters a JSON object (the response from the server).
E.g, suppose that I have this route on my server :
#app.route('/users', methods=['POST'])
def api_login():
if 'username' not in request.json :
return jsonify(success=false)
else :
return jsonify(success=true)
Then, I can in my extenstion, and more precisely in the callback function, check the success value :
function(response) {
if(response.success){
console.log("Login ok !")
}
}
But now, my team doesn't want rely on this anymore, and wants to use http error code instead. I know that flask has an abort function, but while reading the documentation, I have had a lot of trouble to understand what it really does. When I call in my route :
else:
abort(422, {"error":"Missing parameters"})
how can I use these information on the extension (js) ? Does flask automatically returns a specific JSON object when abort is called ? How can I check the error code ? I would like to do something like that in the client code :
if(response.status == 422) {
console.log("Error")
}
One of the clues I have, reading all the StackOverflow threads about abort() is to define a specific error function using the decorator #app.errorhandler(code) :
#app.errorhandler(422)
def myErrorCase(error):
return jsonify(status=422, error="missing parameters")
But I assume that there are more straightforward ways.
Thanks for your help.
Note that i'm using JQuery for this example because it's easier and saves you from a lot of stress and cross-browser issues.
If you just pass in the error code like you're already doing, Werkzeug wraps the error message in html (Though you can still use regex to extract the error message on the client side, but that isn't really flexible). So No Flask doesn't automatically return a JSON string back to the client
The flask abort method either accepts an error code or it can accept a Response object. To achieve what you want to do, you have to pass a Response object to the abort method.
The Response Object is a wrapper around the werkzeug.wrappers.Response object
There also a helper method to create a response object called make_response so you don't have to fiddle with the Response class if you just want to create a simple Response object
One of the reasons you'll create a Response object instead of allowing render_template or abort do it for you is when you need to add a custom header to a response or change the default headers that abort adds to the response.
app.py
from flask import Flask, abort, render_template, Response
from json import dumps
app = Flask(__name__)
#app.route('/')
def home():
return render_template('client.html')
#app.route('/resource')
def resource():
error_message = dumps({'Message': 'You cannot see this!!!'})
abort(Response(error_message, 401))
if __name__ == '__main__':
app.run()
client.html
<html>
<head>
<title></title>
<meta content="">
<style></style>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous">
</script>
</head>
<body>
<script>
$.ajax({
url: 'http://localhost:5000/resource',
dataType: 'json',
success: function(data){
alert('Your request was successful');
},
statusCode: {
401: function (response) {
error = JSON.parse(response.responseText)
alert(error.Message)
}
}
});
</script>
</body>
</html>
You can handle different error codes by defining a corresponding function for them under statusCode
You can still do this from pure Javascript, It just involves more keystrokes.
You should really read through werkzeug's source code to get a better understanding on how abort and exceptions are generally handled. This would be a good starting point

I wanted to get data from server using flask and jQuery

So I tried javascript below
$(document).ready(function () {
$("#mtime").bind("click", function (e) {
$.getJSON('/test', function(data){
if(data.result==15){
alert("success!");
}else{
alert("fail....");
}
});
});
});
And made route using flask like this
#app.route('/test',methods=[GET,POST])
def test():
return jsonify(result=15)
But when I clicked the 'mtime' , alert method did not work.
And got this message from cmd window
"GET /test HTTP/1.1" 404 -"
How can i make it work?
As PJ Santoro wrote there are the quotation marks missing around GET and POST. However you don't need to add the methods explicitly as you only make a GET request which is the default.
from flask import Flask, render_template, jsonify
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/test')
def test():
return jsonify(result=15)
if __name__ == '__main__':
app.run(host='localhost', port=5000, debug=True)
Also it's better practice if you use url_for in your HTML file to generate the url for your endpoint. This way you can be sure the url changes when you decide to change your subdomain or use a Blueprint.
$(document).ready(function () {
$("#mtime").bind("click", function (e) {
$.getJSON({{ url_for('test') }}, function(data){
if(data.result==15){
alert("success!");
}else{
alert("fail....");
}
});
});
});

Categories

Resources