Employing Post Method in Flask - python

Using the following:
from flask import Flask, render_template
import beautiful_soup_tidal
app = Flask(__name__)
#app.route('/')
def form():
return render_template('form_submit.html')
#app.route('/richmond', methods=['POST'])
def richmond():
someTides = beautiful_soup_tidal.getTides()
return render_template('richmond.html',someTides=someTides)
if __name__ == "__main__":
app.run(debug=True)
And attempting to render the following (richmond.html):
<div id="content" class="form-group">
<form method="post" action="/richmond">
<label style="vertical-align: middle;">channel depth at mean low water
<input type="number" step="0.1" value = "34.5" name="channelDepth"/>FEET</label><br><br>
<label style="vertical-align: middle;">required underkeel clearance
<input type="number" step="0.1" value = "2" name="underkeelClearance"/>FEET</label><br><br>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
I get the following error: 'The method is not allowed for the requested URL.'
If I delete ', methods=['POST']' in the first section the template renders.
The question: How do I render the template successfully using the post method?

i believe this line should also include GET so that you can render the html form first time round before you actually click submit to post it.
#app.route('/richmond', methods=['POST'])
so it would change to
#app.route('/richmond', methods=['GET', 'POST'])

Related

Flask Application Showing 404 on Post

This is my first attempt at deploying a machine learning application and also my first time using flask. Essentially the user will fill out a form on an html page and the input from the form will be used as input to the machine learning model which is saved in a pickle file, model.pkl in the code below. I am running into one snag that I can't seem to break past..
Every time I submit from index.html and post to result.html I'm receiving a 404 error.
script.py:
#importing libraries
import os
import numpy as np
import flask
import pickle
from flask import Flask, render_template, request
app=Flask(__name__)
#app.route('/')
#app.route('/index')
def index():
return flask.render_template('index.html')
def ValuePredictor(to_predict_list):
to_predict = np.array(to_predict_list).reshape(1,12)
loaded_model = pickle.load(open("model.pkl","rb"))
result = loaded_model.predict(to_predict)
return result[0]
#app.route('/result',methods = ['POST'])
def result():
if request.method == 'POST':
to_predict_list = request.form.to_dict()
to_predict_list=list(to_predict_list.values())
to_predict_list = list(map(int, to_predict_list))
result = ValuePredictor(to_predict_list)
if int(result)==1:
prediction='Income more than 50K'
else:
prediction='Income less that 50K'
return render_template("result.html",prediction=prediction)
index.html:
<html>
<body>
<h3>Income Prediction Form</h3>
<div>
<form action="/result.html" method="POST">
<label for="age">Age</label>
<input type="text" id="age" name="age">
<br>
<label for="edu">Education</label>
<select id="edu" name="edu">
<option value="0">High School</option>
<option value="1">College Degree</option>
</select>
<br>
<label for="martial_stat">Marital Status</label>
<select id="martial_stat" name="martial_stat">
<option value="0">not married</option>
<option value="1">married</option>
</select>
<br>
<label for="gender">Gender</label>
<select id="gender" name="gender">
<option value="0">Female</option>
<option value="1">Male</option>
</select>
<br>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
result.html:
<html>
<body>
<h1> {{ prediction }}</h1>
</body>
</html>
I can't seem to figure this out. My code never seems to reach the first line in the result() function. As soon as I submit from index.html http://127.0.0.1:5000/result.html throws a 404 error. Any suggestions?
The error is very simple here, the action property in index.html should just be
<form action="/result" method="POST">
instead of
<form action="/result.html" method="POST">
You want to use /result to go through your flask function. Hope this helps!
You are posting to the endpoint /result.html:
<form action="/result.html" method="POST">
... but your route in flask is defined as /result (with no .html):
#app.route('/result',methods = ['POST'])
def result():
...
These two need to match, so consider changing the route to result.html.
Instead of <form action="/result.html" method="POST">
Can Use <form action="{{ url_for('result') }}" method="POST">

How to print/Display my search results on the same webpage using Flask and HTML?

I have a dataset of Players and the number of goals they have scored, this dataset is stored in a dataframe. I want to display or print the stats and player details that I have searched for on the search bar, but I am always getting a bad request error
This is the dataset Dataset Screenshot
this is how the Webpage looks like Webpage screenshot
MainProject Python file
import pandas as pd
from pandas import DataFrame
from fuzzywuzzy import process
scorers=pd.read_csv('tests.csv')
def main(searchplayer):
scorers=pd.read_csv('tests.csv')
player=list(scorers['Player'])
goals=list(scorers['Goals'])
team=list(scorers['Team'])
df_data={'player': player,
'goals': goals,
'team': team}
df_main=pd.DataFrame(df_data, columns=['player', 'goals', 'team'])
def getSearchedProducts(searchplayer, choices, limit=30):
res=process.extract(searchplayer, choices, limit=limit)
return res
searchplayer=str(searchplayer)
result=getSearchedProducts(searchplayer, player)
player_result_list = [res[0] for res in result if res[1]>=70]
player_result_df = df_main[df_main['Product'].isin(product_result_list)]
player_result_df.index+=1
list_player_res=[(tabulate(player_result_df, headers='keys', tablefmt='psql'))]
return list_player_res
Flask File
import os
from flask import Flask, flash, request, render_template,
redirect, url_for, send_from_directory
from werkzeug.utils import secure_filename
from MainProject import main
from flask_cors import CORS
searchplayer=""
app=Flask(__name__)
app.config['CACHE_TYPE']='null'
CORS(app)
#app.route('/', methods=['GET', 'POST'])
def homepage():
searchplayer=request.form['prod']
list_player_res = main(searchplayer)
return render_template('home.html', list_player_res=list_player_res)
if __name__ == "__main__":
app.run()
A code snippet of my Html file
<form class="form-inline" method="POST">
<input class="form-control mr-sm-2" name="prod" type="search" placeholder="Search for Players" aria-label="Search">
<button class="btn btn-light my-sm-0" type="Submit">Search</button>
</form>
This is what I tried:
#app.route('/')
def homepage():
return render_template('home.html')
#app.route('/searchpg', methods=['GET', 'POST'])
def searchpg():
global searchplayer
if request.method == 'POST':
searchplayer = request.form.get['prod']
list_res, list_prod_res = main(searchplayer)
print(list_player_res)
return render_template('home.html', list_player_res=list_player_res)
HTML This is what I did:
<form class="form-inline" method="POST">
<input class="form-control mr-sm-2" name="prod"
type="search" placeholder="Search for Players" aria-label="Search">
<button class="btn btn-light my-sm-0"
type="Submit">Search</button>
</form>
</div>
</nav>
<br>
{% for result in list_player_res %}
{{result}}
{% endfor %}
</br>
How do I search for players in that searchbar and the results get displayed on the same screen?

Passing data from HTML form through Flask to an API [duplicate]

This question already has answers here:
Get the data received in a Flask request
(23 answers)
Post values from an HTML form and access them in a Flask view
(2 answers)
Closed 3 years ago.
So I'm currently making an application in Python that would show live departures and then show a countdown when there are 0 minutes to departure. What my issue is that I don't want to edit the code to change stops, I want to just be able to input the route_type and stop from the html formand then pass that via Flask to the API.
The API is the PTV Timetable API that includes real time departures.
The API has a Swagger page so I know what to insert.
So what I've done is added the authentication code and then added the forms from bootstrap into the HTML file. I've tried googling the problem but I don't really know how the HTML forms can talk to flask so it can get added to the API.
Thanks
Python Code
def getUrl(request):
DevId = <ID>
apikey = <KEY>
request = request + ('&') if ('?' in request) else '?')
raw = 'request' +'DevId={0}'.format(DevId)
hashkey = hmac.new(key, raw, sha1)
signature = hashkey.hexdigest()
return ''https://timetableapi.ptv.vic.gov.au'+raw+'&signature={1}'.format(devId, signature)
from_zone = tz.gettz('UTC')
to_zone = tz.gettz ('Australia/Melbourne')
#get next departures
url = getUrl('/v3/departures/route_type/{route_type}/stop/{stop_id}')
#app.route('/')
#app.route('home')
def home():
return flask.render_template('home.html')
HTML Code
<body>
<form>
<div class="form-group">
<label for="station-id-input">Station ID</label>
<input type="text" class="form-control" placeholder="Station ID">
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-train" value="route_type0">
<label class="form-check-label" for="inline-train">Train</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-tram" value="route_type1">
<label class="form-check-label" for="inline-train">Tram</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-bus" value="route_type2">
<label class="form-check-label" for="inline-train">Bus</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-vline" value="route_type3">
<label class="form-check-label" for="inline-train">V/Line</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline-nightbus" value="route_type4" disabled>
<label class="form-check-label" for="inline-train"Night Bus (Not Implemented)</label>
</div>
</body>
So a good and well documented way to communicate with flask from html is via flask wtforms. It helps you essentially to validate your forms in the html and to secure the POST requests from the frontend usually via a CSRF token.
From the documentation you have a minimal example that could be a good starting point for you:
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
class MyForm(FlaskForm):
name = StringField('name', validators=[DataRequired()])
HTML
PS: The curling brackets are from jinja2, a templating language for python.
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="Go">
</form>
Validating
#app.route('/submit', methods=('GET', 'POST'))
def submit():
form = MyForm()
if form.validate_on_submit():
return redirect('/success')
return render_template('submit.html', form=form)
It is fairly straightforward, you create a form, pass it to the frontend together in the routing and then when the user submits it it tries to validate it.
With all that said, if all you want is to simply send a form data and process that in flask, all you really need to do is create / accept POST requests in your endpoint:
#app.route('/', methods=('GET', 'POST'))
#app.route('home')
def home():
if request.method == 'POST':
form = request.form
value1 = form['value1']
# do something with the values from the form.
return flask.render_template('home.html')
I would not recommend due to validation / security concerns, but it could be a starting point if you are new to flask.

How to execute Python program within #app.route without 405 error?

I am trying to execute this python back end program once I reach the handle data page. Why are the methods returning a 405 Method Not Allowed error?
In the past, I've tried changing the position of the python to outside of the # decorator and the methods=["POST"] condition
Python
import random
import requests
import time
from datetime import date
import sys
import re
import json
from bs4 import BeautifulSoup
from flask import Flask, render_template, jsonify
app = Flask(__name__)
#app.route("/")
#app.route("/home")
def home():
return render_template('home.html')
#app.route("/handle_data")
def handle_data():
userName = requests.form['username']
listName = requests.form['listname']
full python code is here
randomNumber = randint(0,len(nameList)-1)
films = nameList[randomNumber]
return render_template('home.html', films=films)
if __name__ == '__main__':
app.run(debug=True)
...
HTML
<form action="{{ url_for('handle_data') }}" method="POST">
<form>
<div class="form-row">
<div class="col">
<input type="text" size=15 name=username class="form-control" placeholder="Username">
</div>
<div class="col">
<input type="text" size=15 name=listname class="form-control" placeholder="List Name">
</div>
</div>
<p><input type = "submit" class="buttonclass" value = "Random!" /></p>
</form>
I expect the program to run the requests from the form through the program and return the random list item in form of the variable "films" but I receive a 405 error.
If you need more info, please notify
#app.route("/handle_data") registers the route only for GET requests. If you want POST too, you need to ask for it explicitly:
#app.route("/handle_data", methods=['GET', 'POST'])
def handle_data():
# your code here
or:
#app.route("/handle_data", methods=['GET'])
def handle_get_data():
pass
#app.route("/handle_data", methods=['POST'])
def handle_post_data():
pass
More here: http://flask.pocoo.org/docs/1.0/api/#url-route-registrations

session.get('name') returns none, not form data

I have done a lot of research through multiple posts about this issue, and and no matter what I try I am getting issues. Essentially what I am trying to do it write something in an input field, press a submit button and post the string from the input field and display it on a separate page/separate route in using flask. I think I am on the right track with what I have below, however it returns a value of None rather than what I write in my input field in index.html.
from flask import Flask, render_template, request, jsonify, Response,
redirect, url_for,session
from flask_bootstrap import Bootstrap
app = Flask(__name__)
Bootstrap(app)
app.secret_key = 'dljsaklqk24e21cjn!Ew##dsa5'
#app.route('/', methods=['GET', 'POST'])
def hello():
if request.method == 'POST':
nme = request.form['name']
session['name'] = nme
return url_for(deliver)
return render_template('index.html')
#app.route('/delivery', methods=['GET', 'POST'])
def deliver():
name = session.get('name')
return render_template('delivery.html', name=name)
index.html is
<form action = "{{ url_for('deliver')}}" method = "POST">
<p>Name <input type = text class="form-control" name = "name" /></p>
<p>Address <input type = text class="form-control" name = "Address" /></p>
<input type=submit name='submit'>
</form>
and delivery.html is
<div class="card-deck mx-auto" style="width: 75rem;">
<div class="card text-white bg-dark p-3" style="width: 45rem;">
<h5 class="card-title text-center"></h5>
<img class="card-img-top mx-auto" src="/static/img/hands.png" alt="Vibration
Image" style="width:20%">
<div class="card-body">
<h2 class="card-title text-center">Delivery Information</h2>
<h5> {{name}} </h5>
This code:
<form action = "{{ url_for('deliver')}}" method = "POST">
means that submitting the form will POST to /deliver, but you really want to POST to the index page to trigger the session['name'] = nme code. So just remove the action.
You also need to change
return url_for(deliver)
to
return redirect(url_for('deliver'))

Categories

Resources