Post throwing 500 error - javascript

I'm writing a small app. Here is the code snippet.
Javascript:
<script type="text/javascript">
function filldata()
{
var sample = document.getElementById("filter-select").value;
jQuery.support.cors = true;
$.post("/test",{"filter_type":sample},function(data,status)
{
alert(data);
});
}
</script>
Flask Code:
#app.route('/test', methods=['POST'])
def test(str):
return str
It is giving me 500 internal error.
When I run this in debug mode, it is saying:
test() takes exactly one argument(zero given)

Your code:
#app.route('/test',methods=['POST'])
def test(str):
return str
Expect a variable named str in input.
With flask, when defining route the arguments of the function represent the url variables:
# the url have a parameter
#app.route('/user/<id>',methods=['GET'])
def test(id): # we get it here
return user.fromId(id)
To retrieve querystring you can use request.args. And to get body request.data or request.json if you are sending json.
from flask import request
#app.route('/test',methods=['POST'])
def test():
return request.data

You need to parse argument from Flask's request object
from flask import request
#app.route('/test',methods=['POST'])
def test():
return request.form.get('filter_type')
See quickstart for more info

In your Flask code snippet, you have added an argument, but arguments are only sent if you change the URL to /test/<str:str>. Since it is a POST request, you can access the data by using request.json.

Related

How to render template sent as response from Flask app in ajax?

I'm working with Python Flask application that uses basic html and javascript for the web part.
I'm sending data from UI to the backend using ajax post request.
After processing of data, from the Python flask app I'm returning the response with render_template. But I'm not able to understand how that can be rendered using ajax on the web browser.
The python flask API returns this:
#app.route("/execution_pipeline", methods=['POST', 'GET'])
def execution_pipeline():
try:
if request.method == 'POST':
inputMap = request.get_json()
print(inputMap)
###I have my code here###
return render_template('demo.html', location=minio_results_file_location)
except ReferenceError as e:
return "It is a {} Provide proper referaece of file path"
The "demo.html" is a template in the code directory which i want to load on successful execution
And The ajax function is as follows:
$.ajax({
type: "POST",
url: "execution_pipeline",
data: JSON.stringify(data),
contentType : "application/json",
success: function(response) {
window.location.href = response.redirect;
}
});
But on the web page, where we try to load this Ajax response, i'm getting URL not found.
Is there any solution to this?Or am i doing anything wrong?
Import jsonify and url_for from flask:
from flask import jsonify, url_for
And try returning like this to the ajax call:
#app.route("/execution_pipeline", methods=['POST', 'GET'])
def execution_pipeline():
try:
if request.method == 'POST':
inputMap = request.get_json()
print(inputMap)
###I have my code here###
return jsonify({'redirect': url_for('demo.html', location=minio_results_file_location)})
except ReferenceError as e:
return "It is a {} Provide proper referaece of file path"

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 write data to iframe via Flask POST method

I have an old application based on Python SimpleHTTPServer that I'm trying to convert to Flask.
In the old application, I had an HTML form that was submitting a POST request to the SimpleHTTPServer. The form also had an iframe. There, I had a do_POST method that was reading the values in the text boxes and producing some results. I then wrapped the results into a JSON object and wrote to the wfile method of SIMPLEHTTPServer. This caused the result to get populated into the iframe. The iframe had an onload method on the JS side and here, the results would be read from it and populated into various text-boxes.
I now want to convert this to Flask from SimpleHTTPServer. What is the best way to translate the logic I have in place to Flask? Basically, what is the equivalent of writing to the wfile object?
Also, on the Flask side, I also have some #app.route methods where I can form a URL with input parameters and get the results as JSON objects (example: http://localhost/calculate?input1=3&input2=5). Is it possible to leverage these URLs instead of the POST request to get the result into JavaScript?
Here is hello world of flask to get the data from URL parameters and do the stuff and return a json
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/')
def hello_world():
param1 = request.args.get('param1')
param2 = request.args.get('param2')
res = param1 + param2
return jsonify({
"result": res
})
if __name__ == '__main__':
app.run()
example request
GET http://127.0.0.1:5000/?param1=hi&param2=there
Example response
{
"result": "hithere"
}

How to send a single string to python function from ajax query

Context: I am using JavaScript to send a string as a parameter to a python function over the flask.
But I always get "the missing 1 parameter error" on the python side.
This is what my Ajax query looks like:
$.ajax({
url : 'ListMaker',
data: 'Q1',
success: function(data) {
//does something
}
});
This is what my python function looks like:
#app.route("/ListMaker",methods=["POST","GET"])
def ListMaker(text):
#make it a string just incase
quarter=str(text)
//do things with string
Any other similar questions I can find online, only talk about issues with Ajax and don't really cover the python side. In my case, the function is clearly being called, but it claims to receive no data to work with.
Am I sending the data wrongly from the Ajax side? Or am I parsing it wrongly on the python side?
Clarification for NoneType error from the comments below:
I am sending over:
data: JSON.stringify({"letter": "Q", "value": "25%"})
I am receiving it on the python side like so:
data=request.get_json()
letter=data["letter"]
value=data["value"]
The parameters in a Flask route are for variables in the path, called "variable rules" in Flask:
#app.route("/ListMaker/<text>", methods=["POST", "GET"])
def ListMaker(text):
...
As jQuery Ajax requests are GET by default, your data will be converted to a query string, in this case /ListMaker?Q1. You can access the query string in Flask with flask.request.args.
However, query strings are key-value, and you are only supplying a key, which will correspond to the Python dict {'Q1': ''}. You should either set the Ajax data to a string like quarter=Q1, or use an object:
$.ajax({
url : 'ListMaker',
data: {'quarter': 'Q1'}, // or 'quarter=Q1'
success: function(data) {
//does something
}
});
Then you will be able to access it in Flask:
#app.route("/ListMaker", methods=["POST", "GET"])
def ListMaker(): # no parameters needed
quarter = flask.request.args["quarter"]
# quarter == "Q1"
If you want to use a POST request, set method: 'POST' in the Ajax-call, and use flask.request.get_data() or flask.request.get_json() on the Flask side.

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

Categories

Resources