Display selected form items in another page with Flask - python

I'm using Flask 0.12 with Python 3.6 to create a simple app that will display selected items in another page when the submit button is clicked.
The main Flask app is in app.py as:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/result', methods=['POST'])
def result():
return render_template('result.html')
This renders the following webpage using Bootstrap:
<h1>Example Page</h1>
<p>Choose the options in the form below then submit your selections.</p>
<form action="">
<div class="form-group">
<label for="vehicle">Vehicle</label>
<select id="vehicle" class="form-control">
<option>truck</option>
<option>car</option>
<option>van</option>
</select>
</div>
<div class="form-group">
<label for="year">Year</label>
<select id="year" class="form-control">
<option>1972</option>
<option>1999</option>
<option>2010</option>
</select>
</div>
</form>
<br>
<button type="submit" class="btn btn-default">Submit</button>
How can I get Flask to show the selected items in my results.html template when the submit button is clicked?

You have to make few changes in the form to display in result page.
You have to add action url and method in form
<form action="/result" method="post">
Add name in the select field
<select id="vehicle" class="form-control" name="vehicle">
<select id="year" class="form-control" name="year">
Use flask request to get the form values
from flask import request
# inside your POST view
vehicle = request.form.get('vehicle')
year = request.form.get('year')
return render_template('result.html', vehicle=vehicle, year=year)
Finally in your result html page add these...
{{ vehicle }} {{ year }}

Related

Why is my flask application following the error route?

I am trying to write a code (CS50) that uses flask and HTML and I am supposed to create a server where you can input your name as well as a provided option. After this, the results are displayed in a table, the file is called registration.html, (using HTML) as well as recorded in a SQL database.
This is the code for app.py
from cs50 import SQL
from flask import Flask, redirect, render_template, request
app = Flask(__name__)
db = SQL("sqlite:///froshims4.db")
OPTIONS = [ "Stochastic Calculus",
"Financial Engineering",
"Statistical Sciences",
"Algorithmic Progression Systems",
"Econometrics"]
#app.route("/")
def index():
return render_template("index.html", options=OPTIONS)
#app.route("/register",methods=['POST'])
def register():
name = request.form.get("name")
option = request.form.get("option")
if not name or option not in OPTIONS:
return render_template("error.html")
db.execute("INSERT INTO registrants (name,option) VALUES (?,?)",name,option)
return redirect ('/registrants')
#Flask includes a redirect function which redirects to another route.
#app.route("/registrants")
def registrants():
registrants = db.execute("SELECT * from registrants ")
return render_template("registrants.html", registrants=registrants)
This is the code for index:
{% extends "layout.html" %}
{% block body %}
<h1>Register</h1>
<form action="/register" method="post">
#we plan to create a register route
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
<!--a select menu is sort of like a drop down menu <select name="sport"> <option disable selected>Sport</option> -->
<!-- A radiobutton is mutually exclusive checkbox where the user can sign up for only one option-->
{% for option in options %}
<input name="option" type="checkbox" value="'{{option}}">{{option}}
{% endfor %}
</select>
<input type="submit" value="Register">
</form>
{% endblock %}
app.py directs me to error.html even if I have entered a name and a feasible option. Why is this? How can I fix it? Thank you in advance!
<input name="option" type="checkbox" value="'{{option}}">{{option}}
You have an extra single-quote inside value=. So the actual value being returned is e.g. 'Stochastic Calculus which does not match any value in the OPTIONS list.
Also you don't have a closing </option> tag.

How to get select tag value in flask

I have a total of two python scripts. One for the flask itself, and another for backend calculations. And I have an HTML file.
In backend.py:
def get_country():
county_name = ["Bangladesh", "India", "USA"]
country_default = "Bangladesh"
return country_name, country_default
In flask_app.py:
import backend
from flask import Flask
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
country_name, country_default = backend.get_country()
return render_template("index.html", country=county_name, default=country_default)
In index.html:
<form action="" class="form-text" method="GET">
<div class="row">
<div class="col-10">
<select name="select_country" class="form-select form-select-lg mb-3" aria-label=".form-select-lg example">
{% for country in country %}
<option value="{{country}}">{{country}}</option>
{% endfor %}
</select>
</div>
<div class="col-2">
<button type="submit" class="btn btn-outline-primary">Select</button>
</div>
</div>
</form>
<p>You have selected {{default}}</p>
The questions I have here are:
How can I make the select tag in the HTML file to select the default
value initially?
How can I submit the select tag value in the html file and update the
country_default variable in the backend.py?
Answers to your questions:
You can declare the first option to be the default value using the selected attribute in the option tag. Then, you should remove the default value from the country_name.
You can submit the select tag in 2 ways, either using GET Method or POST Method.
Your index.html should looks like this:
<form action="/" class="form-text" method="GET/POST (Choose One)">
<div class="row">
<div class="col-10">
<select name="select_country" class="form-select form-select-lg mb-3" aria-label=".form-select-lg example">
<option value="{{default}}" selected>{{default}}</option>
{% for country in country %}
<option value="{{country}}">{{country}}</option>
{% endfor %}
</select>
</div>
<div class="col-2">
<button type="submit" class="btn btn-outline-primary">Select</button>
</div>
</div>
</form>
<p>You have selected {{default}}</p>
Your backend.py should looks like this:
def get_country(default):
county_name = ["Bangladesh", "India", "USA"]
country_default = "Bangladesh"
if default in country_name:
country_default = default
country_name.remove(country_default)
return country_name, country_default
If you use GET Method, then it will redirect you to the "/" route with a query parameter (select_country). The route might look like this, "/select_country=(value_selected)". You can get the query parameter in flask using request.args.get(query_name). Your flask_app.py should look like this:
from backend import get_country
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def home():
country_name, country_default = get_country(request.args.get("select_country"))
return render_template("index.html", country=county_name, default=country_default)
If you use POST Method, then it won't change the route. Therefore there wouldn't be any query parameters. You should instead use requests.form.get(name) to get the posted data. Your flask_app.py should look like this:
from backend import get_country
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
country_name, country_default = get_country(request.form.get("select_country"))
return render_template("index.html", country=county_name, default=country_default)

Getting None from request.form.get()

I need to get data from 2 different forms. The first "index.html" rendering takes a user's selected option and stores it on the variable "item".
on "page2.html", the "item" value is shown here just fine. And again, the user is entering some new data on the textbox input and then it's redirected to the next rendering, "page3.html"
on "page3.html", it is supposed to show both data from the forms on "index.html" and "page2.html" but i'm getting "None" when I try to show the "item" value. Why?
I've tried to do it on separate app.route() routes, but I got the None type value as well.
the app.py file:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if request.form.get('send') == 'send':
item = str(request.form.get('test1'))
return render_template('page2.html', item=item)
if request.form.get('send2') == 'send2':
item = str(request.form.get('test1'))
text = request.form.get('textbox')
return render_template('page3.html', item=item, text=text)
else:
return render_template('index.html')
app.run(debug=True)
the index.html file:
<div align="center">
<form method="POST" action="{{ url_for('index') }}">
<select name="test1">
<option name="1" value="1">1</option>
<option name="2" value="2">2</option>
<option name="3" value="3">3</option>
</select>
<button type="submit" name="send" value="send">Send</button>
</form>
</div>
the page2.html file:
<div align="center">
<form method="POST" action="{{ url_for('index') }}">
<h2>Previous selection: {{ item }}</h2><br>
<input type="text" name="textbox" value="Enter text">
<button type="submit" name="send2" value="send2">Send</button>
</form>
</div>
and the page3.html file:
<div align="center">
<h2>Your result is:</h2><br>
<h2>"{{ text }}" and "{{ item }}" </h2>
</div>
store the value of item in a session so that you can access it later. Once you are done you can clear the session like session.pop("session_name", None)
if request.form.get('send') == 'send':
item = str(request.form.get('test1'))
session["test1"]=item
return render_template('page2.html', item=item)
if request.form.get('send2') == 'send2':
item = session.get("test1")
text = request.form.get('textbox')
return render_template('page3.html', item=item, text=text)

Why I am getting Bad request error for this flask page?

I have two flask form in same page. One form is visible at the beginning and user have to select an option and based on that the second form is generated. Second from contains a dropdown which will submit the form on onchange event. When this submission occurs I am getting bad request error. My Html form is:
<form action="/ip" method="POST" name="btn" value="project">
<label>Select Project : </label>
<select class="form-control" style="width: 50%;display:inline-block" name="project_name">
<option></option>
<option value="k">Ki</option>
<option value="s">S</option>
<option value="l">L</option>
</select>
<button type="submit" class="btn btn-primary m-b-10 m-l-5" style="display:inline-block" ">Fetch Details</button>
</form>
<form method="POST" action="/ip" name="btn" value="dlvr">
<select id="subsystem_value" onchange="this.form.submit()">
{% for i in data %}
{% for k in i %}
<option value={{ k }}>{{ k }}</option>
{% endfor %}
{% endfor %}
</select>
</form>
and my flask view is :
#auth.route('/ip',methods = ['POST', 'GET'])
def ip():
if request.method == 'POST':
if request.form['btn'] == "project":
project = request.form['project_name']
c, conn = connection()
subsystem = "SELECT distinct sub from ip where project='{}'".format(project)
query = "SELECT distinct del from ip where project='{}'".format(project)
c.execute(query)
data = c.fetchall()
c.execute(subsystem)
subsystem = c.fetchall()
sub = []
for row in subsystem:
for id in row:
sub.append(id)
conn.close()
return render_template('ip.html', data=data,sub=sub)
else:
subsystem = request.form['subsystem_value']
return render_template('ip.html')
else:
return render_template('ip.html')
I tried to make same name for forms and gave separate values too. But still I am getting bad request error.
I have two areas where your error is coming from
1) Form name is deprecated since HTML 4 and is no longer submitted therefore
if request.form['btn'] == "project":
will not be understood by flask
The way to go around that is to give your submit button a name like this
<button type="submit" name="project" class="btn btn-primary m-b-10 m-l-5" style="display:inline-block" ">Fetch Details</button>
and in your flask view, check for the form like this
if 'project' in request.form:
2) The second error is on this line
<form method="POST" action="/ip" name="btn" value="dlvr">
<select id="subsystem_value" onchange="this.form.submit()">
line two here should be name= "subsystem_value", not id="subsystem_value"
otherwise this line in flask will not be understood
subsystem = request.form['subsystem_value']
So I have this simplified code that is no longer giving me an error and returning the values the way I think you want them
in flask
#app.route('/ip',methods = ['POST', 'GET']) #Used #pp.route to match my testing app
def ip():
if request.method == 'POST':
if 'project' in request.form:
project = request.form['project_name']
return str(project)
else:
subsystem = request.form['subsystem_value']
return str(subsystem)
else:
return render_template('test.html')
in the template
<form action="/ip" method="POST" >
<label>Select Project : </label>
<select class="form-control" style="width: 50%;display:inline-block" name="project_name">
<option></option>
<option value="k">Ki</option>
<option value="s">S</option>
<option value="l">L</option>
</select>
<button type="submit" name="project" class="btn btn-primary m-b-10 m-l-5" style="display:inline-block" ">Fetch Details</button>
</form>
<form name method="POST" action="/ip" >
<select name="subsystem_value" onchange="this.form.submit();">
<option value="test1">t1</option>
<option value="test2">t2</option>
<option value="test3">t3</option>
</select>
</form>
Hope that helps you out
You are in the perfect position to avail yourself of Flasks debug facilities, which you can activate by either setting the environment variable FLASK_DEBUG=1 or by passing debug=True to app.run().
See http://flask.pocoo.org/docs/1.0/api/#flask.Flask.debug
Also, if there's any chance that this code will face hostile users, use SQL bind variables instead of constructing a query from untrusted input. A SQL Injection attack can ruin your day.

How to configure html for selectfield(wtforms) flask?

Good evening to everyone who reads this post.
I want to add a select box to my web site in flask, but i can not understand how to set up html for that
I look forward to see any comments and suggestions :)
My python code:
class selectmenu(Form):
month = SelectField('Choose month',choices=[('dec', 'dec'), ('yan', 'yan'), ('feb', 'febt')])
#app.route('/searchemp/', methods=['GET', 'POST'])
def searchemp():
form = selectmenu(request.form)
m = form.month.data
HTML:
<form action="" class="form-signin" method="post">
<h2 class="form-signin-heading" align="center">title</h2>
<input type="text" class="form-control"
placeholder= "username" name="username" value="{{request.form.username}}" required autofocus>
<!--
<input type="text" class="form-control"
placeholder= "month" name="month" value="{{request.form.month}}">
-->
<select name="month">
<option value="{{request.form.month}}">dec</option>
<option value="{{request.form.month}}">yanuary</option>
<option value="{{request.form.month}}">feb</option>
<option value="{{request.form.month}}">mar</option>
</select>
<button class="btn btn-lg btn-success btn-block" type="submit">Search</button>
<br>
<p align="center">{{error}} </p>
</form>
Jinja2 template engine will render selectfield with choices, you dont have to create a html select field, jinja2 already does. And if you need to check form submission use validate_on_submit() or request.method == 'POST':
class SelectMenu(Form):
month = SelectField('Select Month', choices=[(1, 'January'), (2,'February')])
#app.route('/searchemp/', methods=['GET', 'POST'])
def searchemp():
form = SelectMenu(request.form)
if form.validate_on_submit():
# get posted data
m = form.month.data
return render_template('index.html', form=form)
# index.html
<form action="" method="POST">
{{form.month.label}}{{form.month}}
</form>

Categories