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)
Related
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 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
I have the following AJAX PUT request that was given to me. I'd like to run it from a Python script. I'm new to everything AJAX/HTTP related, so I'm guessing. Here's the request:
$.ajax({
url: <insert base URL here> + "/state",
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify({
state: "<insert state here>",
state_modified_by: $.cookie("<insert username here>")
}),
complete: function(data) {
document.location.reload();
}
})
Here's my attempt at implementing the same request in Python using the requests library:
import requests
url = <insert base URL here> + "/state"
data = json.dumps({"state" : "<insert state here>", "state_modified_by" : "<insert username here>"})
headers = {"Content-Type":"application/json"}
response = requests.put(url, headers = headers, data = data)
That gets me a "bad request" response from the URL.
Things I'm definitely unsure about:
- Is using the requests library even the best route? Is there an easier way to run jQuery type stuff from Python?
- Is json.dumps equivalent enough to JSON.stringify?
- What is "$.cookie" and how do I do something similar in Python?
- How do I do the "completion event" that the AJAX request does using requests in Python?
Any help is greatly appreciated - thanks very much!
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.
I'm using Google App Engine (Python) along with jQuery for Ajax calls to the server. I have a page where I want to load up a list of strings in Javascript from an Ajax call to the server.
The server method I want to invoke:
class BrowseObjects(webapp.RequestHandler):
def get(self):
ids_to_return = get_ids_to_return()
// TODO: How to return these ids to the invoking ajax call?
self.response.out.write(ids_to_return)
The HTML page where I want to be able to access the returned ids:
var strings_from_server = new Array();
$.ajax({
type: "GET",
url: "/get_ids.html",
success: function(responseText){
// TODO: How to read these IDS in here?
strings_from_server = responseText
},
error: function (xhr, ajaxOptions, thrownError){
alert(xhr.responseText);
}
});
My experience with Ajax is limited-- I've only used them to store data to the server (a-la POST commands) and so I really have no idea how to get data back from the server. Thanks in advance for all help
Edit: My final answer:
I've switched to a full Ajax call (to prevent from cross-domain requests) and also to handle 'error' callbacks. My working client method looks like:
$.ajax({
type: "GET",
dataType: "json",
url: "/get_ids.html",
success: function(reponseText){
strings_from_server = responseText
},
error: function (xhr, ajaxOptions, thrownError){
alert(xhr.responseText);
}
});
Note I specify the dataType as 'json'.
And my final server function, with sahid's answer, looks like:
class BrowseObjects(webapp.RequestHandler):
def get(self):
ids_to_return = get_ids_to_return()
# Note: I have to map all my objects as `str` objects
response_json = simplejson.dumps(map(str, ids_to_return))
self.response.out.write(response_json)
Thanks all!
The SDK of Google AppEngine provided by django the lib "simplejson".
from django.utils import simplejson
So your handler maybe it simply:
from django.utils import simplejson
class BrowseObjects(webapp.RequestHandler):
def get(self):
ids_to_return = get_ids_to_return()
response_json = simplejson.dumps (ids_to_return)
self.response.out.write(response_json)
There are a good article about ajax/rpc: http://code.google.com/appengine/articles/rpc.html
It's probably not the cleanest solution, but it will work. Since they are just IDs, it sounds like it's safe to push them directly into a string.
class BrowseObjects(webapp.RequestHandler):
def get(self):
ids_to_return = get_ids_to_return()
response_html = '["'
response_html += ids_to_return.join('","')
# Edit: since my ids are Key objects (not strings)
# I had to use the following instead:
# response_html += '","'.join(map(str, ids_to_return))
response_html += '"]'
self.response.out.write(response_html)
and
var strings_from_server = new Array();
$.getJSON("/get_ids.html", function(responseData){
strings_from_server = responseData;
});
You can check to see if the response was empty incase of an error, and you can use $.each to loop through the results.
I am using jQuerys getJSON feature to automatically parse the response. Since I'm just returning a json list, it will generate the array of data in the strings_from_server variable.