Unable to parse json data from ajax in flask - python

I am trying to pass data from ajax to routes.py in flask through json. I have sometimes made it pop up a dialog box with the actual data, but I am unable to parse the data or have it appear on a webpage itself..(I eventually need to have this data manipulate sql db but for now I am just trying to be able to manipulate the data).
routes.py
#app.route("/post", methods=['GET', 'POST'])
def post():
data = request.get_json()
jsonify(data=data)
x = request.json['index']
return render_template('post.html', x=x)
request.json['index'] does not work and throws TypeError: 'NoneType'
if I return jsonify(data=data) instead of have it before the return, I can see the data in a dialog window when I go to localhost:5000/post
index.html
<script>
$(function() {
$( "#sortable" ).sortable({
update: function(event, ui) {
var postData = $(this).sortable('serialize');
}
});
});
function postSave() {$( "li" ).each(function( index ) {
console.log( index + ": " + $( this ).attr('id') );
$.ajax({
url: '/post',
data: JSON.stringify({ "index" : index, "id" : $( this ).attr('id') } ),
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
alert(JSON.stringify(data));
}
});
var url = "/post";
$(location).attr('href',url);
});
}
</script>
post.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- simply be able to parse through the data and print it here for testing purposes -->
</body>
</html>
all help is greatly appreciated, I am pulling my hair out as we speak :)

Your post route has been configured to handle both GET and POST requests, but you don't distinguish between GET and POST requests. Since there is no distinction between the two type of requests if your browser sent off a GET request to your post route on your flask server there will be no JSON data in your request. A simple conditional like the following: if flask.request.method == 'POST': can be used to distinguish between the two types of requests. With that being said, maybe you could try out something like the following:
#app.route('/post', methods=['GET', 'POST'])
def post():
if request.method == "POST":
req_data = request.get_json()
x = req_data['index']
return render_template('post.html', x=x)
else: # GET request
# handle as you see fit probably want to render a page
# with inputs for a user to fill out
return render_template(<page_you_wish_to_render>)
If this doesn't work could you please print out req_data? So we can see what the request looks like as it might be invalid JSON.
Also, your ajax call looks a little off, maybe you could edit just the Ajax part to something like the following:
$.ajax({
type : 'POST',
url : "{{url_for('post')}}",
contentType: 'application/json;charset=UTF-8',
data : {'index':index}
});
Lastly, I would put a debugger statement right before you send off your ajax request to make sure the request is correct.
Hopefully that helps!

Related

JQuery ajax - how to send JSON with GET method?

I'm trying to send some data from JQuery.ajax() to my python Flask server, JS code is:
let data = JSON.stringify({nickname: "AAA", password: "BBB"});
$.ajax({
async: true,
data: data,
dataType : "json",
contentType: "application/json",
method: "GET",
url: "/test_back",
success: function() {},
error: function() {}
});
Python code is:
#app.route("/test_back", methods=["GET", "POST"])
def test_back():
print(request)
data = request.get_json()
print(data)
return jsonify({})
And print(data) is writing None in console, so I can't read it as a dict.
When I change method: "GET" to method: "POST", it works just fine.
So: how do I send JSON from JQuery to Flask, using method GET, correctly?
First of all add conditional for flask methods get and post its good practices :D
if request.method == "POST":
if request.method == "GET":
also try return the data not the empty jsonfy
return data
not
return jsonify({})_

Issue with sending data to python flask from AJAX

I am not able to retrieve data field of AJAX in python flask.
Its shows type error when I try to retrieve data. type and forwho are of array type. When I alert them in AJAX it works.
Here is my code,
// Ajax
$.ajax({
url: '/products',
data: JSON.stringify({'type':type,'forwho': forwho}),
contentType: "application/json; charset=utf-8",
type: 'POST',
success: function(response){
/*alert("success");*/
$("#content").html(response);
},
error: function(error){
/*alert("error");*/
console.log(error);
}
});
# app.py
#app.route('/products', methods =['POST', 'GET'])
def all_products():
if request.method == 'POST':
print("inside all products post")
type = json.loads(request.form.get('type'))
forwho = json.loads(request.form.getlist('forwho'))
print(type)
print(forwho)
when I print print(request.args.get('typearr')) in all_products() it returns None
type =request.json['type']
forwho = request.json['forwho']
Flask automatically parses JSON when having application/JSON in your request.
This solution finally worked for me.
ajax:
data: JSON.stringify({'typearr':type,'forwho':forwho})
``````````````````
app.py:
#import ast
``````````````
data = request.get_data()
data = ast.literal_eval(data.decode("UTF-8"))
typearr = data['typearr']
forwho = data['forwho']

Why when I render Django template on ajax, success does not appear on the browser?

My Html page isn't rendered on ajax success when I use console.log() in the js file, the HTML page is printed out in the browser console but not in the browser itself.
kindly check my following code:
views.py:
def Filter_by_Products(request):
if request.is_ajax():
if request.method == 'GET':
print("filter by function!")
filter_brand = request.GET.get('filter_brand')
products_qs, qs_color, qs_size = product.objects.Filter_brand(filter_brand.rstrip(','))
context={
"object_list": products_qs,
'colors': qs_color,
'sizes':qs_size
}
# print(products_qs)
# print(qs_color)
# print(qs_size)
return render(request,"product/products.html",context)
ajax.js:
$.ajax({
url:'/cart/api/filterby/',
method:'get',
data:
{
'filter_brand':str,
},
success: function (data) {
console.log(data)
// location.reload()
},
error: function (error) {
console.log(error)
}
})
After googling on my question, I found that my problem is that I'm trying to mix the server side with the client side and the solution is to send my HTML template using HttpResponse not render function and then by using javascript, I select the HTML page and change content with the new html.
Actually, I didn't understand clearly the problem and why mixing server with client caused that problem and why my code wasn't working from the first time using render, so could you please explain more in details or refer links to me to understand.
also, I'm familiar with Django celery and Redis, if i can use those technologies in that situation, could you just refer to me how to use them.
When i'm working with Django and Ajax, i like to use JsonResponse, a library from django.http. This way, I can pass the status response (200, 500, ...), and the data that will be treated in front.
The problem in your case, is that after you received the response, you are reloading the page.
// location.reload()
As your responde data is an object, you have to define, using javascript, where it will be placed on the screen, for example:
success: function (data) {
console.log(data);
$("#div_object_list").html(data.object_list);
},
No problem in return render(request,"product/products.html",context), it will return a rendered html page's content.
The problem is in your ajax request calling: // location.reload(), referring to w3schools.com it reloads current page only without replacing page's content with returned response.
If you need to replace the entire page with returned response, so your ajax success function should like:
success: function (response) {
var newDoc = document.open("text/html", "replace");
newDoc.write(response);
newDoc.close();
}
If you just need to replace with specific html div, you can do:
success: function(response) {
$('#my-div').html(response);
}

Passing data between client and Flask

I have a Flask application where I have a form that collects some user input. That input is then passed as JSON data via an AJAX call to a function in my Python script.
This function calls an API, gets some new data and then returns a redirect URL to the AJAX call. On success, AJAX then redirects to this new template with window.location.href.
I tried 'passing' the first view function, the_search, over to the second view function to then render the appropriate template but this didn't do the trick unfortunately. I've also tried setting the data as a session variable and then accessing it in the template but this doesn't seem to work either.
My issue
How can I access the variable 'response' within the redirected template, results.html?
AJAX script
...
$.ajax({
type: 'POST',
url: '/the_search',
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: function(data, status) {
window.location.href = data['website'];
},
error: function() {
console.log('there was an error');
}
})
...
Python script
#app.route('/the_search', methods=("POST", 'GET'))
def the_search():
data = json.loads(request.data)
lat = data['latitude']
longitude = data['longitude']
response = unirest.get("https://zilyo.p.mashape.com/search?latitude={}&longitude={}".format(lat, longitude),
headers={
"X-Mashape-Key": "k6HBYxvy88mshQ6Yg1xPVuv7Vg9Np1GZj7IjsnPxploykdpaHA",
"Accept": "application/json"})
session['search_results'] = response.body
return jsonify({'website': '/results'}), 200
#app.route('/results', methods=('POST', 'GET'))
def results():
#How can I pass the_search view function to here while still having access to the response data
print session['search_results']
return render_template('results.html')

How to parse Cordova/Phonegap file upload in flask app

I've been working on a Cordova app, using the Ionic framework. I'm trying to do a "File Transfer" to a my Python-Flask back-end, but I keep getting "400 Bad Request". I'm quite sure that the error is caused by the request parsing method in flask (I'm currently using "request.file[]").
But I can't seem to figure out how to parse the POST request properly.
The POST is send in chunkedMode, with the mime type "image/jpeg", not sure if this could have any impact (My Nginx proxy is set up to properly receive POSTs in chunked mode).
My client code:
$scope.getPhoto = function() {
$scope.modal.show();
navigator.camera.getPicture(
// Succes
function(imageURI){
// Upload image
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType = "image/jpeg";
options.trustAllHosts = true;
options.chunkedMode = true;
var ft = new FileTransfer();
// Initiate upload
ft.upload(imageURI, encodeURI("http://192.168.1.53/"),
// Succes
function(succes){
alert(succes.response);
console.log(succes.response);
},
function(error){
alert(error.target);
console.log(error);
},
options
);
},
// Error
function(message) {
console.log('get picture failed');
},
// Options
{
quality: 100,
encodingType: Camera.EncodingType.JPEG,
allowEdit : false,
correctOrientation: true,
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY
}
);
I got this working in PHP, witht the following code:
if(isset($_FILES["somefile"]))
{
//Filter the file types.
if ($_FILES["somefile"]["error"] > 0)
{
echo "error:" + $_FILES["somefile"]["error"];
}
else
{
callSomeFunction();
}
} // End of function
My current flask app looks something like this:
#app.route("/", methods=["GET", "POST"])
def upload_file():
if request.method == "POST":
file = request.files["file"]
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
#fileStream = file.stream
#print(opencvDataFromStream(fileStream))
#processImage(filename)
return processImage(filename)
return """
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
"""
As you can see it returns a form, and when the POST is send through the form, the request is treated as expected.
But when the POST request is send through the cross side Cordova client, I get the bad request error.
Would any one happen to know how to fix this?
Sincerely a flask n00b.
So I screwed up...
The error was simply caused, due to the fact, that the fileKey ("imageToScan") parameter in the client wasn't the same fileKey as my Flask back-end was expecting ("file").

Categories