Python 3 Flask Rest API Get multiple argument - python

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.

Related

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

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/

Requesting a resource results in a 404 (Flask)

As I'm testing the URL endpoint for a resource, I'm getting a 404 Not Found error. I don't understand why it cannot be found as the resource is added to the api instance and the blueprint is added to the flask app.
tests.py
def test_todo_collection_resource(self):
with app.test_client() as client:
http_response = client.get("/todos/")
json_data = http_response.get_json()
self.assertEqual(http_response.status_code, 200) <<<---FAILS
self.assertTrue(http_response.is_json)
self.assertTrue(all(
(instance['name'] in self.todo_resources.values()
for instance in json_data)
))
todos.py
from flask import Blueprint, jsonify
from flask_restful import Api, Resource, fields, marshal
from models import Todo
todo_api = Blueprint("resources.todos", __name__)
api = Api(todo_api)
todos_fields = {
'name': fields.String
}
class TodoList(Resource):
pass
api.add_resource(
TodoList,
''
'todos'
)
app.py
from flask import Flask, g, jsonify, render_template
from config import HOST, PORT, DEBUG
from peewee import *
import models
from resources.todos import todo_api
app = Flask(__name__)
app.register_blueprint(todo_api, url_prefix="/todos/")
models.DATABASE.init('todo_api.db')
models.initialize(models.User, models.Todo)
#app.route('/')
def my_todos():
return render_template('index.html')
if __name__ == '__main__':
app.run(host=HOST, port=PORT, debug=DEBUG)
You have not defined any methods in your TodoList class that is why there is a 404 error as it can't find any HTTP methods defined on that endpoint. The Flask-RESTful documentation specifies defining HTTP methods in your Resource class e.g.
class TodoList(Resource):
def get(self):
return TODOS

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)

Registering multiple restplus blueprints on same prefix doesn't work

So I'm building an API with Flask-RestPlus and using blueprints to divide the code into smaller chunks, but when trying to register multiple API endpoint, providing same URL prefix, only one blueprint registers.
Blueprint Templates:
from flask import Blueprint
from flask_restplus import Api, Resource
tmpl_bp = Blueprint('templates_api', __name__)
api = Api(tmpl_bp)
ns_tmpl = api.namespace('templates', description='Templates operations')
#ns_tmpl.route('/')
class Templates(Resource):
def get(self):
return "All templates"
def post(self):
return "Added/updated template"
Blueprint Render:
from flask import Blueprint
from flask_restplus import Api, Resource
rend_bp = Blueprint('render_api', __name__)
api = Api(rend_bp)
ns_render = api.namespace('render', description='Render actions')
#ns_render.route('/')
class Render(Resource):
def post(self):
return "Rendering everything"
The main app code, where registering happens:
from flask import Flask, render_template
from api.templates import tmpl_bp
from api.render import rend_bp
app = Flask(__name__)
app.register_blueprint(tmpl_bp, url_prefix="/api/v1")
app.register_blueprint(rend_bp, url_prefix="/api/v1")
#app.route('/')
def home():
return "This is the main page"
The resulting Swagger API:
I was expecting both the Templates and the Render blueprints to be served on /api/v1/ as /api/v1/templates and /api/v1/render respectively. But only one registers every time.
How do I get both blueprints served under the same prefix?
You don't need to use Blueprint, it's enough to use flask_restplus Namespaces.
Flask-RESTPlus provides a way to use almost the same pattern as Flask's blueprint. The main idea is to split your app into reusable namespaces.
from flask import Flask, render_template
from flask_restplus import Resource, Api
from api.templates import tmpl_bp
from api.render import rend_bp
app = Flask(__name__)
api = Api(app)
api.add_namespace(tmpl_bp, path="/api/v1/templates")
api.add_namespace(rend_bp, path="/api/v1/render")
#api.route('/')
def home():
return "This is the main page"
You can find out more details here https://flask-restplus.readthedocs.io/en/stable/scaling.html

404 when accessing resource Flask-Restful

from flask import g, request, session, render_template, flash, redirect, url_for
from flask import current_app as app
#app.route('/')
def home():
return 'this works'
from flask_restful import Resource, Api
from app.extensions import api
class HelloWorld(Resource):
def get(self):
return {'Hello': 'World'}
api.add_resource(HelloWorld, '/test') # Getting a 404 for this route on http://127.0.0.1:5000/test
Extensions sets up the api variable:
api = Api()
api.init_app(app)
I cannot figure out why I get a 404 when trying to access an api resource?
Ok, the problem seems to be that the below ordering is wrong. I must add resources before I init the api.
api = Api()
api.init_app(app)
api.add_resource(HelloWorld, '/')
Fix:
api = Api()
api.add_resource(HelloWorld, '/')
api.init_app(app)
This is quite strange given that e.g. SQLAlchemy needs to call init_app before it is used...

Categories