I am experimenting with Flask and AJAX, I have a simple API route here , hosted at OpenShift. I want to call the API in a Javascript file with Ajax. The OpenShift Python file is simple:
from flask import Flask
app = Flask(__name__)
import json
#app.route('/hello/<name>')
def hello_world(name=None):
str = {'key':'Hello World!', 'q':name}
#out = {'key':str}
res = json.dumps(str)
return res
if __name__ == '__main__':
app.run()
And here is the Ajax call:
$.ajax({
type:"GET",
dataType: "json",
data:'Payam',
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/",
success: function(data){
buf1=data;
console.log(data);
}
})
But this makes a call to this url which results in 404. How can I solve this? Just to mention CORS is not an issue.
http://mypythonapp-spacepirate.rhcloud.com/hello/?Payam
Try changing your url property to
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/world",
Then you will get a 200 response status, instead of the 404. The reason is the flask route you created has a required parameter after the hello/.
edit: followup to question about using variable for the data
method1: just add encode the parameter to the url
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/" + encodeURIComponent(xyz)
method2: use the data parameter to the ajax call as you have started to do. I think that jquery will translate that into the URL query string for a get, like this. Notice the ? delimiting the start of query string:
http://mypythonapp-spacepirate.rhcloud.com/hello/?xyz
You can verify that by checking in your browser dev tools and seeing what URL the ajax call is actually requesting. Also note that in the flask handler you would then need to check for request.query_string to get the data, because <name> parameter would be empty.
Using the guidelines provided by Alex G Rice and the answers here Python Flask how to get parameters from a URL? I found out how to pass the data directly as following:
The Ajax call:
$.ajax({
type:"GET",
dataType: "json",
data:{'name':'Payam'},
url: "http://mypythonapp-spacepirate.rhcloud.com/hello/",
success: function(data){
buf1=data;
console.log(data);
}
})
The python file:
#app.route('/hello/', methods=['GET','POST'])
def hello_world(name=None):
buf1 = request.args.get('name')
str = {'key':'Hello World!', 'q':buf1}
#out = {'key':str}
res = json.dumps(str)
return res
Related
I passed a list data selectedOrder from python to html as below.
return render_template(f"fillForm.html", items=selectedOrder)
I know there is a way to send a single data from html either by using input form or appending data to url as in /fillForm?sid=3&quantity=5 but I'm curious if I can send a list data from html back to python in such a manner as well. Obviously I can just store the data to some variable within python before passing it but given how my code is working, it would be better to directly get the data from html if possible. Not sure if this will matter, but I use flask and jinja2 template.
You could use an ajax request and send your list as a json. Flask provides the method request.get_json() to retrieve the json data received as a dict. Assuming you have jquery it would be like:
$.ajax({
url: "/your_route",
type: "POST",
contentType: "application/json;charset=UTF-8",
dataType: "json",
data: JSON.stringify({html_data: yourlist}),
success: function(response) {
console.log(response);
},
});
Then on flask side:
#app.route('/your_route')
def your_route():
data = request.get_json()
print(data['html_data']) # should print your list
# don't forget to return a success status
I am trying to pass some data from the frontend to the backend of my site using AJAX. This is the post request view in my django views:
def post(self, request):
id_ = request.GET.get('teacherID', None)
print(id_)
args = {}
return JsonResponse(args)
This is the function I have in javascript. I know the correct value is being passed because the console.log(teacher_id) prints the right value.
function send(teacher_id){
console.log(teacher_id)
var url = window.location.pathname;
$.ajax({
method: "POST",
url: url,
data: {
'teacherID': teacher_id,
},
dataType: 'json',
success: function (data) {
//location.href = data.url;//<--Redirect on success
}
});
}
When the code is run, and the print statement in my view is run, regardless of what the teacher_id is, None is printed.
what is wrong with the code?
In your Django view the data is being retrieved using GET.get() while the AJAX request is sending it using method: "POST".
POST data can't be retrieved in the same way as GET data so you should either change the way the data is being send (by changing the method in the AJAX call to GET) or read it using the related POST methods.
You can visit this Stack Overflow question if you are doubting which method to use.
I've created a page that interacts with an app written with Python on GAE, to return JSON data (via JSONP, because Cross-origin stuff). However, no matter what method I use, the page always hangs and data never actually makes it to the screen. It runs just fine if I request the stuff by typing the appspot URL into my address bar, though.
Here's the main part of le code.
Python main.py (on GAE)
def retrieve_data(self):
# Retrieve data from some API, manipulate and return result.
# Note: I'm not using this handler for the request.
# It's just there in case I need it.
class MainHandler(webapp2.RequestHandler):
def get(self):
data = retrieve_data(self)
self.response.headers["Content-Type"] = "application/json"
self.response.out.write(
json.dumps(data)
)
# I'm using this handler for the JSONP request.
class JSONPHandler(webapp2.RequestHandler):
def get(self):
data = retrieve_data(self)
self.response.headers["Content-Type"] = "application/json"
self.response.out.write(
"%s(%s)" %
(urllib2.unquote(self.request.get("callback")),
json.dumps(data))
)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/jsonp', JSONPHandler)
], debug=True)
index.js (Not hosted on GAE)
function add(data) {
// Sort data, add to DOM.
}
$.ajax({
type: "GET",
dataType: "jsonp",
url: "(APPSPOT URL)/jsonp",
success: function(data) { add(data) }
});
I've also tried $.get, creating a script tag with a src pointing to the appspot link, and other XMLHTTPRequest methods people described, but none seem to work.
If I tell success to just console.log the data, it will do so after a few seconds of running.
So, is there something wrong with the code? Am I missing something in main.py, or am I AJAXing it wrong?
I used this code to receive cross-origin json request POST data in my webapp2 handler:
def options(self):
self.response.headers['Access-Control-Allow-Origin'] = '*'
self.response.headers['Access-Control-Allow-Headers'] = '*'
self.response.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
def post(self):
self.response.headers['Access-Control-Allow-Origin'] = '*'
self.response.headers['Access-Control-Allow-Headers'] = '*'
self.response.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
data = self.request.body
args = json.loads(data)
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.
Imagine that you need to write some Javascript that simply changes a set of checkboxes when a drop down list is changed.
Depending on which item is selected in the list, some of the checkboxes will become checked/unchecked.
In the back, you have Python code along with some SQLAlchemy.
The Javascript needs to identify the selected item in the list as usual, send it back to the Python module which will then use the variable in some SQLAlchemy to return a list of checkboxes which need to be checked i.e. "User selected 'Ford', so checkboxes 'Focus', 'Mondeo', 'Fiesta' need to be checked"
The issue Im having is that I cant seem to find a way to access the python modules from the Javascript without turning a div into a mini browser page and passing a url containing variables into it!
Does anyone have any ideas on how this should work?
Funny, I've got web pages with JavaScript that talk to Python CGI modules that use SQLAlchemy.
What I do is send AJAX request but with JSON request in the body instead of XML. Python CGI modules use standard json module to deserialize JSON into a dictionary.
JavaScript side looks like this:
function on_request_success(response) {
console.debug('response', response);
}
function on_request_error(r, text_status, error_thrown) {
console.debug('error', text_status + ", " + error_thrown + ":\n" + r.responseText);
}
var request = { ... };
jQuery.ajax({
url: 'http://host/whatever.cgi',
type: 'POST',
cache: false,
data: JSON.stringify(request),
contentType: 'application/json',
processData: false,
success: on_request_success,
error: on_request_error
});
And Python like this:
request = json.load(sys.stdin)
response = handle_request(request)
print("Content-Type: application/json", end="\n\n")
json.dump(response, sys.stdout, indent=2)
Note, it doesn't use Python cgi module, since the whole request is passed as JSON in the body.
python has a json module, which is a perfect fit for this scenario.
using a good old AJAX, with json as the data format will allow you to exchange data between javascript and your python module.
(unless your python module is running on the client side, but then i don't see how you could execute it from the browser...)
Ajax is a good way to pass variables between python and javascript.
Javascript:
param = {a:'hello', b: 'world', c: '!'}
$.ajax({
type: "post",
url: "scpi.py",
cache: false,
async: 'asynchronous',
dataType: 'html',
data: param,
success: function(data) {
console.log(data)
},
error: function(request, status, error){
console.log("Error: " + error)
}
})
Server.py: (You will need a three functions for this to work)
def do_POST(self):
if "scpi.py" in self.path:
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD': 'POST'}
)
a = form['a'].value
b = form['b'].value
c = form['c'].value
content = myfunction(a, b, c)
self.respond(content)
def handle_http(self, data):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
print(data)
return bytes(str(data), 'UTF-8')
def respond(self, data):
response = self.handle_http(data)
print(data)
FYI: "myfunction(a, b, c,)" is a function from another python file, then return the data and passes to self.respond to send back to javascript