Why is my POST getting a 405? Python-Flask API - python-3.x

I'm currently writing an API in Flask, and am currently trying to me my POST request to work. Ideally, it would add a band to the DB with a band_ID, name, genre, number of gigs, and a rating. For some reason, running the proper POST request in postman returns a 405. I didn't even know an API *I made * would tell me I don't have access to a POST I'm writing. Do I need to change anything to make it have access?
from flask import Flask, request
from flask_restful import Api, Resource
import sqlite3
app = Flask(__name__)
api = Api(app)
class Band(Resource):
def get(self, band_id):
conn = sqlite3.connect('database.db')
c = conn.cursor()
c.execute("SELECT * FROM bands WHERE band_id=?", (band_id,))
result = c.fetchone()
if result:
return {"message": result}
else:
return {"message": "Band not found"}
def post(self):
data = request.get_json()
if not all(key in data for key in ('band_name', 'band_genre', 'gigs', 'rating')):
return {"message": "Missing data"}
band_name = data['band_name']
band_genre = data['band_genre']
gigs = data['gigs']
rating = data['rating']
conn = sqlite3.connect('database.db')
c = conn.cursor()
c.execute("INSERT INTO bands (band_name,band_genre,gigs,rating) VALUES (?,?,?,?)", (band_name,band_genre,gigs,rating))
conn.commit()
return {"message": "Success"}
api.add_resource(Band, '/bands/<int:band_id>')
if __name__ == "__main__":
conn = sqlite3.connect('database.db')
c = conn.cursor()
c.execute("DROP TABLE IF EXISTS bands")
c.execute("""CREATE TABLE IF NOT EXISTS bands (
band_id INTEGER PRIMARY KEY,
band_name TEXT,
band_genre TEXT,
gigs INTEGER,
rating INTEGER
)""")
conn.commit()
app.run(debug=True)
I've tried changing the call on postman and fiddling around with my add.resource lines but to no avail. Totally lost on what to do next.

Related

How to do pagination in flask

**python code:**
from flask import Flask, render_template, request, redirect, url_for, session ,flash
from flask_mysqldb import MySQL
import MySQLdb.cursors
import re
app = Flask(__name__)
app.secret_key = 'your secret key'
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = ''
app.config['MYSQL_DB'] = 'details'
mysql = MySQL(app)
#app.route('/home')
def home():
if 'loggedin' in session:
cur = mysql.connection.cursor()
cur.execute("SELECT * FROM ml_process_status")
data = cur.fetchall()
return render_template('home.html', username=session['username'], items=data)
return redirect(url_for('login'))
There are 50 rows in phpmyadmin mysql database. Is there any solution to show only 10 rows in first page and next 10 rows in other pages. I have select * query to show all the rows in the page
To do this you have to pass a parameter to your endpoint (which indicates the page to be displayed), and to select the range of records concerned by using OFFSET AND LIMIT inside your sql statement.
Example:
#app.route('/home')
def home():
if 'loggedin' in session:
page = request.args.get('page', 1)
elem_to_display = 10
offset = (page - 1) * elem_to_display
cur = mysql.connection.cursor()
cur.execute("SELECT * FROM ml_process_status LIMIT %s OFFSET %s", (elem_to_display, offset,))
data = cur.fetchall()
return render_template('home.html', username=session['username'], items=data)
return redirect(url_for('login'))

Unable to write mitmproxy flow results to sqlite3 database

I am trying to store the mitmproxy flows to the database for further processing but when using the following code to insert into the sqlite3 database it's just skipping the insert into the database line and no data gets saved nor any errors are showing.
from mitmproxy.options import Options
from mitmproxy.proxy.config import ProxyConfig
from mitmproxy.proxy.server import ProxyServer
from mitmproxy.tools.dump import DumpMaster
import sqlite3
conn = sqlite3.connect('traffic.db')
c = conn.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS traffic (
id INTEGER PRIMARY KEY,
path,
method,
status,
request,
response
)""")
conn.commit()
class Addon(object):
def __init__(self):
self.num = 1
def request(self, flow):
print("flow.request.path")
print(flow.request.path)
c.execute("INSERT INTO traffic VALUES (null, :path, :method, :status, :request, :response)",
{'path': flow.request.path, 'method': flow.request.method, 'status': flow.response.status_code,
'request': flow.request.get_content(), 'response': flow.response.content})
conn.commit()
flow.request.headers["count"] = str(self.num)
def response(self, flow):
self.num = self.num + 1
flow.response.headers["count"] = str(self.num)
print(self.num)
if __name__ == "__main__":
options = Options(listen_host='0.0.0.0', listen_port=8080, http2=True)
m = DumpMaster(options, with_termlog=False, with_dumper=False)
config = ProxyConfig(options)
m.server = ProxyServer(config)
m.addons.add(Addon())
m.run()
What is the correct way of doing this?
I used your code but a different approach, that I used for writing to text file before.
However, this seems to work, so thank you for the SQL part!
import sqlite3
conn = sqlite3.connect('/home/pi/mitm/traffic.db')
c = conn.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS traffic (
id INTEGER PRIMARY KEY,
path,
method,
status,
request,
response
)""")
conn.commit()
def response(flow):
c.execute("INSERT INTO traffic VALUES (null, :path, :method, :status, :request, :response)",
{'path': flow.request.path, 'method': flow.request.method, 'status': flow.response.status_code,
'request': flow.request.content, 'response': flow.response.content})
conn.commit()
The I use mitmdump instead of mitmproxy this way:
mitmdump -s the_code_above.py
This works for me, hopefully it helps for your case, too.

PokeAPI & Flask: Combining different properties on API

API beginner here,
I'm creating an API that calls both a character name and their description with one ENDPOINT. So far I have the data appearing at separate endpoints.
Goal: Getting output format ('http://127.0.0.1:5000/v1/pokemon/string:name') to look similar to this:
{ "name": "pichu", "description": "It is not yet skilled at storing electricity.It may send out a jolt if amused or startled."}
from flask import Flask, jsonify, Response
from flask_restful import Resource, Api, fields, marshal_with
import requests, json
app = Flask(__name__)
api = Api(app)
# Prints all Pokemon via JSON
#app.route('/v1/pokemon/all', methods=['GET'])
def poke_names():
data = []
name_url = "https://pokeapi.co/api/v2/pokemon?limit=151"
while True:
resp = requests.get(name_url)
json = resp.json()
data.extend(json.get('results', []))
name_url = json.get('next')
if not name_url: break
return jsonify(data)
#app.route('/v1/pokemon/<string:name>/title', methods=['GET'])
def get_poke(name):
return jsonify({'name': name})
#flavor Text ie pokemon description
#app.route('/v1/pokemon/<int:pokemon_id>', methods=['GET'])
def get_description(pokemon_id):
descrip_url = f"https://pokeapi.co/api/v2/pokemon-species/{pokemon_id}"
r = requests.get(descrip_url)
json_blob = r.json()
flav_text = extract_descriptive_text(json_blob)
return jsonify({'description': flav_text})
def extract_descriptive_text(json_blob, language='en'):
text = []
for f in json_blob['flavor_text_entries']:
if f['language']['name'] == language:
text.append(f['flavor_text'])
return text
#error occurs below
#app.route('/v1/pokemon/<string:name>')
def all_poke_data(name, flav_text):
return jsonify({'name':name, 'description':flav_text})
if __name__ == "__main__":
app.run(debug=True)
Error: When I try to combine them I get
TypeError: all_poke_data() missing 1 required positional argument: 'flav_text'
Thank you for any pointers provided!
Figured it out!
Just add this function, which is a combination of both route functions
#app.route('/v1/pokemon/<string:name>')
def get_poke(name):
descrip_url = f"https://pokeapi.co/api/v2/pokemon-species/{name}"
r = requests.get(descrip_url)
json_blob = r.json()
flav_text = extract_descriptive_text(json_blob)
return jsonify({'name': name},{'description': flav_text})

FLASK: The new values entered in the form are not getting inserted to the database even though the execution has been committed

from flask import Flask, jsonify, request, url_for, redirect, session, render_template, g
import sqlite3
app = Flask(__name__)
app.config['DATABASE'] = './data.db'
def connect_db():
path = r"C:\Users\Arjun\Documents\flask_app\data.db"
sql = sqlite3.connect(path)
sql.row_factory = sqlite3.Row
return sql
def get_db():
if not hasattr(g, 'sqlite3'):
g.sqlite_db = connect_db()
return g.sqlite_db
#app.teardown_appcontext
def close_db(error):
if hasattr(g, 'sqlite_db'):
g.sqlite_db.close()
#app.route('/home', defaults={'name':'Default'})
#app.route('/home/<name>')
def home(name):
session['name'] = name
return render_template('home.html', name=name, display = False, mylist = [1,2,3,4]
#app.route('/theform5', methods=['GET', 'POST'])
def theform5():
if request.method == 'GET':
return render_template('form.html')
else:
name = request.form['name']
location = request.form['location']
db = get_db()
db.execute("insert into users (name, location) values (?, ?)", [name, location])
db.commit()
return redirect(url_for('home', name=name, location=location))
#app.route('/viewresults')
def viewresults():
db = get_db()
cur = db.execute('select id, name, location from users')
results = cur.fetchall()
return 'The ID is {}. Name is {}. The location is {}. '.format(results[1]['id'], results[1]
['name'], results[1]['location'])
Error in:
return "The ID is {}. Name is {}. The location is {}".format(results[1]['id'],results[1]['name'],results[1]['location'])
IndexError: list index out of range
Though the table can be edited directly through the terminal, it can't be edited when the flask web app is run.
Browser: Chrome
SQLite: v3.30.1
Python: v3.8.1
Flask: v1.1.1
you have a syntax error in your return statement in your home function. missing ')' at the end.
In order to run db.execute you would have to set up the cursor first:
db = get_db()
cursor = db.cursor()
cursor.execute("insert into users (name, location) values (?, ?)", [name, location])
also, maybe your syntax is off, try this:
cursor.execute("insert into users values('%s', '%s')" %(name, location))
Are these not the answers you are looking for?

Using same connection with multiple resolvers in graphene

I have a code like this,
# SWAMI KARUPPASWAMI THUNNAI
import jwt
import graphene
from flask import request
from auth.helper import medease_token
from database.get_connection import get_connection
from flask_graphql import GraphQLView
class CredentialInformation(graphene.ObjectType):
"""
graphene object type to get the personal information about the user
"""
country_code = graphene.String()
phone = graphene.String()
verified = graphene.Int()
#medease_token
def resolve_country_code(self, root):
customer_token = request.headers["x-access-token"]
decoded_token = jwt.decode(customer_token, verify=False)
customer_id = decoded_token["customer_id"]
try:
connection = get_connection()
cursor = connection.cursor()
cursor.execute("select country_code from customer_credential where id=%s limit 1", (customer_id, ))
result = cursor.fetchone()
return result["country_code"]
finally:
cursor.close()
connection.close()
#medease_token
def resolve_phone(self, root):
customer_token = request.headers["x-access-token"]
decoded_token = jwt.decode(customer_token, verify=False)
customer_id = decoded_token["customer_id"]
try:
connection = get_connection()
cursor = connection.cursor()
cursor.execute("select phone from customer_credential where id=%s limit 1", (customer_id, ))
result = cursor.fetchone()
return result["phone"]
finally:
cursor.close()
connection.close()
#medease_token
def resolve_verified(self, root):
customer_token = request.headers["x-access-token"]
decoded_token = jwt.decode(customer_token, verify=False)
customer_id = decoded_token["customer_id"]
try:
connection = get_connection()
cursor = connection.cursor()
cursor.execute("select verified from customer_credential where id=%s limit 1", (customer_id,))
result = cursor.fetchone()
return result["verified"]
finally:
cursor.close()
connection.close()
def credential_information_wrapper():
return GraphQLView.as_view("graphql", schema=graphene.Schema(query=CredentialInformation))
which uses flask-graphql and graphene for Python graphql. The code works absolutely fine but I think I am missing something here because I need to open new connections in every resolver, and I need to write same query again so there is a data duplication, so is this the right way of doing or am I missing something?
Any help would be highly appreciated! Thank you in advance.
Opening a new connection on every query (resolver in this case) is okay. You could also set a connection pool to minimize the cost of opening connections.
Just curious, what database adapter or ORM are you using? Would be great if you could refactor the connection and cursor steps into a single function to call on every resolver and only have to pass the SQL query string.

Resources