Sending a Post request to Flask API, but not receiving data - python

So I am trying to send certain values to my Flask API streamlit application, but it appears that it is not executing a post request. Right now, the post request code I have for my main.py does not work because I am getting a TypeError: 'NoneType'.
app.py :
import requests
import json
import streamlit as st
...
api_url = "http://127.0.0.1:5000/" # Flask url
create_row_data = {'name': name, 'type': get_type(name), 'token_value': token_value,
'external': external, 'start': start, 'end': end, 'step': step}
print(create_row_data)
# The terminal cannot print out the value of r and it appears that it cannot send the post request as well
r = requests.post(url=api_url, json = create_row_data)
print(r)
Output of print(create_row_data) in app.py:
{'name': 'session', 'type': 'area_chart', 'token_value': 'G0as7vjk1ksuxn94',
'external': False, 'start': datetime.datetime(2021,7,1,14,9,7,322438), 'end': datetime.datetime(2021,7,8,14,9,7,322441), 'step': '1d'}
main.py:
from flask import Flask
from flask import jsonify
from flask import request
...
import requests, json
#app.route('/', methods=['GET', 'POST'])
def get_data():
if request.method == 'GET':
return "ok", 200
if request.method =='POST':
p_name = request.json['name']
p_type = request.json['type']
...
p_end = request.json['end']
p_step = request.json['step']
create_row_data = {'p_name': str(p_name), 'p_type': str(p_type), ... , 'p_end': str(p_end), 'p_step': str(p_step)}
print(create_row_data)
response = requests.post(url, data=json.dumps(create_row_data), headers= {'Content-type': 'application/json'}
return response.content

From my understanding, you need to post data to 127.0.0.1 and process it to create a table from app.py using flask_restful to create an API endpoint so that you can post data. The code for main.py would be:
from flask import Flask
from flask import Flask, request
from flask_restful import Resource, Api
from flask import jsonify
from flask import request
import requests, json
app = Flask(__name__)
api = Api(app)
#app.route('/', methods=['GET', 'POST'])
def get_data():
if request.method == 'GET':
return "ok", 200
class create_row_data(Resource):
def post(self):
response = request.get_json()
p_name = response['name']
p_type = response['type']
...
# code to process your data and to create a table
# return something for your client application
return True
api.add_resource(create_row_data, '/create_row_data/')
No changes are needed for your client app.py except the url which now changes to http://127.0.0.1:5000/create_row_data/

Related

How can the following issue be resolved in flask? "Method Not Allowed The method is not allowed for the requested URL"

Here is the code
import os
import redis
import flask
import json
import urllib.parse
from flask import Flask, Response, request, render_template, abort
from flask_cors import CORS, cross_origin
#from flask.ext.cors import CORS, cross_origin
app = Flask(__name__)
app.config['CORS_HEADERS'] = 'Content-Type'
redis_handle = redis.Redis('localhost')
requiredFields = ("id", "title", "name") # fields required for user object
#app.route('/')
#cross_origin()
def hello():
return 'Hello World!'
#app.route('/users/<user_id>', methods=['GET'])
#cross_origin()
def get_user(user_id):
response = {}
# user_id = request.args.get("id")
user = redis_handle.get(user_id)
if not user:
response["msg"] = "no user found"
return Response(json.dumps(response), status=404, mimetype="application/json")
return user
#app.route('/users', methods=['POST'])
#cross_origin()
def save_user():
data = request.get_json(force=True)
response = {}
if all(field in data for field in requiredFields):
redis_handle.set(data["id"], json.dumps(data))
return Response(status=201)
else:
missing_key = str([val for val in requiredFields if val not in dict(data).keys()])
response["msg"] = "required key " + missing_key + " not found"
return Response(json.dumps(response), status=400)
#app.route('/users/<user_id>', methods=['DELETE'])
#cross_origin()
def delete_user(user_id):
response = {}
resp = redis_handle.delete(user_id)
if resp == 0:
response["msg"] = "no such entity found"
status = 404
else:
response["msg"] = "Delete op is successful"
status = 200
return Response(json.dumps(response), status=status)
#app.route('/clear', methods=['GET'])
#cross_origin()
def clear_data():
redis_handle.flushall()
return "ok!"
if __name__ == "__main__":
app.run(debug=True)
As of my knowledge, I have even included the method = "POST" as well but still don't know what is going wrong.
I tried to create a small crud application using redis, python, flask but couldn't encountering this issue. Can someone tell me where and what am I doing wrong?
Browsers don't run POST methods outside of a <form> entry or AJAX function. Therefore, you're running a GET, which "isn't allowed".
Unclear what you expected, but to see all users, you'll need to edit your route to first add the GET method, then if so, return a response that returns/renders all users rather than checking the request json body, which won't exist for GET requests
If you only wanted to get one user, edit the url to include the user ID
The browser will use the GET method for URLs that you input in URL/search bar but you don't have any function decorated with #app.route('/users', methods=['GET']).
If you want to create a user with POST /users then it would be easier to use some HTTP client like https://www.postman.com, https://insomnia.rest, etc. or even fetch in the browser's console.

Flask routing request url based on request body?

How can I route request based on the request body in flask? I think I can use redirect but I prefer not to use that and to route request immediately based on the content of the body.
Here is what I tried but failed:
# I am using Flask-restful extension
from flask import Flask, request
from flask_restful import Resource, Api
class RouteA:
def post(self):
return {'route': 'RouteA'}
class RouteB:
def post(self):
return {'route': 'RouteB'}
app = Flask(__name__)
api = Api(app) # This is just flask-restful app wrapper extension
# I am trying to use before_request
#app.before_request
def routing():
request_body = request.get_json(force=True)
type = request_body.get('type', None)
if type and type == 'RouteB':
# somehow direct to routeB
request.path = '/jobs/routeb'
# I can do this too but I prefer direct routing rather than redirecting
# return redirect(location='jobs/routeb', code=307)
# routing here
api.add_resource(RouteA, '/jobs')
api.add_resource(RouteB, '/jobs/routeb')
if __name__ == '__main__':
app.run(debug=True)
How I will make request to that endpoint:
import requests
url = 'http://localhost:5000/jobs'
payload = {
'type': 'RouteB'
}
r = requests.post(url=url, json=payload)
response = r.json()
print(response)
# Expecting:
# {'route': 'RouteB'}

Python Flask: Error "The method is not allowed for the requested URL"

I am very new to working with Python Flask and i wanted to try a simple API-example:
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
some_json = request.get_json()
return {'you sent': some_json}, 201
class Multi(Resource):
def get(self,num):
return {'result': num*10}
api.add_resource(HelloWorld, '/')
api.add_resource(Multi,'/multi/<int:num>')
if __name__ == '__main__':
app.run(debug=True)
and if I type in the terminal
-H "Content-Type: application/json" -X POST -d '{"name":"xyz","address":"myaddress"}' http://127.0.0.1:5000/
I get the following message:
{
"message": "The method is not allowed for the requested URL."
}
I hope someone can help me with this...
Since your are calling the POST HTTP method. You should rename 'get' function in class HelloWorld to 'post'. 'HelloWorld' class can also have both 'get' and a 'post' functions if '/' endpoint should serves both.
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def post(self):
some_json = request.get_json()
return {'you sent': some_json}, 201
class Multi(Resource):
def get(self,num):
return {'result': num*10}
api.add_resource(HelloWorld, '/')
api.add_resource(Multi,'/multi/<int:num>')
if __name__ == '__main__':
app.run(debug=True)

Python 3 Flask Rest API Get multiple argument

How to have get rest api on python with multiple arguments? I tested my rest api on IE by the below url
http://127.0.0.1:5002/search_np?item=testing&posn=1
from flask import Flask, request
from flask_restful import Resource, Api
from flask_cors import CORS
....
app = Flask(__name__)
cors = CORS(app, resources={r"*": {"origins": "*"}})
api = Api(app)
api.add_resource(search_nextpage, '/search_np')
....
class search_nextpage(Resource):
def get(self):
search_item = request.args.get('item', "")
search_posn =request.args.get('posn', "")
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class search_nextpage(Resource):
def get(self):
item = request.args.get('item')
posn = request.args.get('posn')
return {'item': item, 'posn': posn}
api.add_resource(search_nextpage, '/search_np')
if __name__ == '__main__':
app.run(debug=True)
Requesting http://127.0.0.1:5000/search_np?item=chocolate&posn=0 yields the following output.
{
"item": "chocolate",
"posn": "0"
}
The arguments item and posn are retrieved from the querystring and returned in a json dictionary.

Flask Print Not Working

If I send run this program to do a HTTP Post to my Flask server, which I know returns a 200 response:
import requests
import json
dump= '{"on": false}'
r = requests.post('http://127.0.0.1:5000', data=dump,
headers={'Content-Type': 'application/json'})
And my Flask server's code:
from flask import Flask
from flask import request, jsonify
import requests
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def signal():
if request.method == 'POST':
content = request.get_json()
return jsonify(content)
print(jsonify(content))
r = requests.put("http://192.168.1.102/api/F5La7UpN6XueJZUts1QdyBBbIU8dEvaT1EZs1Ut0/lights/5/state/", jsonify(content))
else:
return 'Hello, world!'
if __name__ == '__main__':
app.run(debug=True)
I want to print the data to the console, then send it over to a bridge on the network using a HTTP PUT. Neither of these are working, and I'm not sure why.
You need to return at the very end of the function
#app.route('/', methods=['GET', 'POST'])
def signal():
if request.method == 'POST':
content = request.get_json()
print(content)
r = requests.put("http://192.168.1.102/api/F5La7UpN6XueJZUts1QdyBBbIU8dEvaT1EZs1Ut0/lights/5/state/", content)
return jsonify(content)
else:
return 'Hello, world!'
Note: You probably are over-using the jsonify function because the jsonify() function in flask returns flask.Response() object, and not a JSON string that you would POST or PUT to another service.

Categories