There is a client-side JavaScript and server-side Python, powered by Django. There is a data object: foo_data = {"foo":1, "bar":2}.
Now, I would like to send a post-request using dojo/request/xhr, and send foo_data along with another variable:
xhr.post(document.location.href, {
data: {
'is_foo': true,
'data': foo_data
},
headers: { 'Content-Type': 'application/json' }
}).then(function(text){
console.log('The server returned: ', text);
});
And then read sent data in Django's views.py file:
def post(self, request, *args, **kwargs):
json.loads(request.body)
BUT, it doesn't work:
if I ssend foo_data, python doesn't recognize it correctly as JSON object and can't read it using json.loads.
I can't encode foo_data using JSON.parse because it is already an object!
request.POST is an empty QueryDict
request.body has string word object (instead of the real object)
Any ideas how to solve this?
Goal: send JSON object from JS --> Python and read it on server-side.
dojo.xhr has been deprecated, please consider using dojo/request more info here:
https://dojotoolkit.org/reference-guide/1.10/dojo/request/xhr.html#dojo-request-xhr
For a live example of post to a server, you can look source code for this page:
https://dojotoolkit.org/documentation/tutorials/1.8/ajax/demo/dojo-request-xhr-post.php
Here some a simple example of usage:
require(dojo/request"],
function(request){
// post the data to the server
request.post("your/server/script", {
// send your data here
data: { yourData: 1},
// wait 2 seconds for a response
timeout: 2000
}).then(function(response){
// do smt here when operation is successfully executed
});
}
);
Regarding your code sample in your question, you have't posted your server side code. But you could try to pass your data to the server using JSON.stringify().
Related
I have a website with a big form. When I first made the website, I was using a GET request to send the form values to a Python CGI script (using the JavaScript fetch function). In the Python script, I could read the data with parameters = cgi.FieldStorage().
Since a GET request has a limited payload size, I had to switch to a POST request because that request type has no limit.
I changed my JavaScript fetch function to the following to make a POST request:
fetch('../../cgi-bin/saveFormAnswers.py', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-type': 'application/json; charset=UTF-8',
}
})
.then(antwoord => antwoord.json())
.then(data => {
console.log("Return data Python:")
console.log(data);
}
);
However, I can't seem to get the data in the Python CGI script. cgi.FieldStorage() doesn't work anymore. How do I get the POST payload in the Python script and how do I send a (JSON) dictionary back as a response to the POST request?
I'm not using any frameworks like Flask.
EDIT: I came to the conclusion it's related to the JavaScript code and that cgi.FieldStorage() should work. Instead of letting JavaScript do the POST request, I set up the POST request directly in the HTML form which worked just fine without any issues. I'm still trying to figure out what's wrong with my JavaScript code.
Fixed it by using sys.stdin instead of cgi.FieldStorage().
data = ""
if int(os.environ.get('CONTENT_LENGTH', 0)) != 0:
for i in range(int(os.environ.get('CONTENT_LENGTH', 0))):
data += sys.stdin.read(1)
I have a question about JSON.stringify() and how to parse it. I have a frontend code and a backend in python (Django).
My fetch function looks like this in frontend.
const response = await fetch('some-url', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
payload: payload
})
});
When i do console.log on JSON.stringify({payload: payload}), its type is string. Then in my backend code, when i print out request.data['payload']), its type is <class 'dict'>. I am confused why the type changed when i sent the request to the backed. I was going to use json.loads() to parse the payload but since it is already dictionary it returns an error and i can just do request.data['payload'] to access its data.
Can someone explain this behavior?
So I guess you are using Django Rest framework.
request.data
Will in Django Rest provide you with a parsed version of the request body. Because you are using the content-type: json it will try and parse it as .. json.
See docs here: https://www.django-rest-framework.org/api-guide/requests/#data
In regular Django for parsing a JSON request it would require the use of json.loads like:
parsed_json = json.loads(request.body)
I'm writing a very simple demo webapp, and I can't seem to pass a json object from js to python using ajax.
I've tried a number of suggestions from people on so with similar problems, such as using .get_json() instead of .json, passing the object without using JSON.stringify in the javascript, etc.
Any idea what piece I'm missing here?
Javascript
var run_method = function(){
var data1 = {"word":"hello"}
console.log("Before " + data1);
$.ajax({
url : "/examplemethod",
type : "POST",
data : data1//JSON.stringify(data1)
})
.done(function(data){
var data = JSON.parse(data);
console.log(data);
});
}
Python
#app.route("/examplemethod", methods=['POST', 'GET'])
def example_method():
global data
if request.method == 'POST':
print request
data = request.json
print "data", data
return "after "+ data["word"]
Every variation I have tried of this gives a 500 Error, and
TypeError: 'NoneType' object has no attribute 'getitem'
Obviously, that is because data is supposed to be an dictionary/json, not None. But how to I get it to return as a dictionary?
Because you are not sending JSON, to the flask app (see this and this). Your current code results in a standard urlencoded form post. Which in turn results in an entry being populated in request.form
request.form.get('word')
Switch to a json post as per the guidelines in the above Q&As to access the data through request.json.
the data is likely not flowing to json if you are getting None, so you should jsonify the data. It will be coming in in the form of form.
from flask import jsonify
#app.route("/examplemethod", methods=['POST'])
def example_method():
data = jsonify(request.form).json
print(data) #will be in the form a json dict
return data['foo-key'] #can retrieve specific items with their key-pairs
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 trying to post JSON between URLs in my app. The receiving URL expects JSON in the body of the request and responds with JSON in the body of the request. The problem is I can't seem to send JSON in the body using Mootools Request.JSON. This is what I have:
// formObj is an object constructed from a form
var request = new Request.JSON({
url: "/api/object.new",
urlEncoded: false,
onRequest: function(){
// swap submit button with spinner
},
onComplete: function(jsonObj) {
// work with returned JSON
},
body: JSON.encode(formObj)
});
request.setHeader("Content-Type", "application/json");
request.post();
The server returns a 500 error:
BadValueError: Property name is required
Which means that request.name is returning None which means that the server is not getting my JSON.
Using HTTPClient to paste the output of JSON.encode(formObj) into the body field produces the desired results.
body is not a valid mootools property for Request. use data: blah instead. as it stands, data is empty so no wonder you get nothing on the server side...