How to get user selected value from SelectField in python Flask WTF? - python

Here is the code snippet I have written
MainPage.py
from flask import Flask, render_template,url_for,request, redirect
from form import SearchForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey1234'
#app.route("/")
#app.route("/home", methods=['GET', 'POST'])
def home():
forms = SearchForm()
return render_template('home.html', title='Home', forms=forms)
#app.route("/about")
def about():
return render_template('about.html', title='About')
if __name__ == '__main__':
app.run(debug=True)
form.py
from flask_wtf import FlaskForm
import Get_Test_Suite
from wtforms.fields import SelectField, SubmitField
from wtforms.fields.html5 import DateField
from wtforms.validators import DataRequired
class SearchForm(FlaskForm):
test_suite_list = Get_Test_Suite.get_test_suite()
suite_list = []
for i in test_suite_list:
suite_list.append((i, i))
test_suite_selected = SelectField('Test Suite Name', choices=suite_list)
test_module_list = Get_Test_Suite.get_module_name()
module_list = []
for j in test_module_list:
module_list.append((j, j))
test_module_selected = SelectField('Test Module Name', choices=module_list,validators=[DataRequired()])
date_selected = DateField('Date', format='%m-%d-%Y')
status = SelectField('Status', choices=[('Active', 'Active'), ('Closed', 'Closed')])
submit = SubmitField('Submit')
home.html
{% extends "layouts.html" %}
{% block content %}
<div class = "content-section">
<form method="POST" action="">
{{forms.hidden_tag()}}
<fieldset class="form-group">
<legend class ="border-bottom mb-4">
<center>SEARCH TEST FAILURE STATUS</center>
</legend>
<div class="form-group">
{{forms.test_suite_selected.label(class="form-control-label")}}
{{forms.test_suite_selected(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{forms.test_module_selected.label(class="form-control-label")}}
{{forms.test_module_selected(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{forms.date_selected.label(class="form-control-label")}}
{{forms.date_selected(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{forms.status.label(class="form-control-label")}}
{{forms.status(class="form-control form-control-lg")}}
</div>
</fieldset>
<div class="form-group">
{{forms.submit(class="btn btn-outline-info")}}
</div>
</form>
</div>
{% endblock content %}
I am creating many drop down lists in home.html
How can I get the data that the user selects from each of the drop down list and print it ? I am trying to create a user friendly web application where the user will select the values from a drop down list and the application will fetch the data accordingly from the database.

#app.route("/")
#app.route("/home", methods=['GET', 'POST'])
def home():
forms = SearchForm()
if request.method == 'POST':
print(forms.field_name.data) # <- prints to console.
# to print to web convert to variable and render with jinja2
# return render_template('display.html', field_name=forms.field_name.data)
return render_template('home.html', title='Home', forms=forms)

Have you tried transforming the 'choices' into a dict? You can then get the value for the key form data. Maybe something like this (for your "status" SelectField): value = dict(form.status.choices).get(form.status.data)

I sure that you was find your solution, but for next generation.
You need insert in the select tag the name of the value, and not in options tags.
example:
<select name="sServer">
{% for server in servers %}
<option value="{{server}}">{{server}}</option>
{% endfor %}
</select>

Related

Flask Templating Language Not Displaying Properly

My flask template is not displaying properly. For some reason, the templating language is being displayed on the webpage.
Here is what it looks like (red circles indicate items that should not be on the web page)
I am not sure why this is happening. The templates are stored in a folder called static and in my app.py, I have the following line as well:
app = Flask(__name__, template_folder='static')
Edit: Here is the code that renders the following portion of this page:
`
{% if passphrase %}
<div>
<h4>Information</h4>
<p>Address: 123_easy_uncover_street</p>
</div>
{% else %}
<div class="col">
<h4>Enter passphrase</h4>
<form action="" method="POST" style="text-align:left">
<label for="passphrase">Passphrase</label>
<input type="text" id="passphrase" name="passphrase">
<br>
<input type="submit" value="Submit">
</form>
</div>
<div id="status" class="col" >
<p><i>Please enter your passphrase</i></p>
</div>
{% endif %}
</div>`
Flask code:
from app.bank_database import BankDatabase
from flask import Flask, request, render_template
import random
import json
app = Flask(__name__, template_folder='static')
db = BankDatabase()
#app.route('/', methods=['GET', 'POST'])
#app.route('/index.html', methods=['GET', 'POST'])
def index():
return render_template("index.html", passphrase="")
#app.route('/check_passphrase', methods=['GET', 'POST'])
def check_passphrase():
passphrase = request.args.get("passphrase")
if db.check_passphrase(passphrase):
#Show address here
#TODO - change view to show passphrase
return render_template("index.html", passphrase=passphrase)
return render_template("index.html", passphrase="")
app.run(debug=True,host="0.0.0.0")

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)

Flask, Passing User Entered Data Between Views

Problem transferring variables across views I tried using sessions and could not get the connection to work. Say I have two pages, a home and page2. I have a flask app that will take user input from the home and print out input on page2.
For example, if you start my app, you will see this as the home page:
This part works fine, I am able to enter a value.
What I want to happen next, is after you click submit, page2 is generated showing what was just entered:
Whatever string value was entered on home should show up in the highlighted portion.
I have the following app.py file:
from flask import Flask, render_template, request, session
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
stringval = ''
if request.method == 'POST' and 'stringval' in request.form:
stringval = request.form.get('stringval')
session["stringvalue_topass"] = stringval
return render_template('page2.html', stringval = stringval)
return render_template("home.html")
#app.route('/page2', methods=['GET', 'POST'])
def page2():
stringvalue_get = session.get('stringvalue_topass')
return render_template('page2.html', stringvalue_get = stringvalue_get)
if __name__ == '__main__':
app.run(debug=True)
The following home.html:
<!doctype html>
<h1>Enter Value </h1>
<div class="main">
<form class="pure-form" method="POST" action="/page2">
stringval:<br>
<input type="text" name="stringval"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit!</button>
</form>
</div>
</body>
And the following page2.html
<!doctype html>
<h1>You have selected </h1>
<div class="main">
{% if stringvalue_get %}
<pre>
{% print(stringvalue_get) %}
</pre>
{% endif %}
</div>
</body>
Okay, there are a few issues here. Firstly, the action attribute of your form in home.html is set to "/page2". This means that when the form is submitted, the POST request is going to the /page2 endpoint rather than to the /home endpoint, where you have written the code for handling the form submission. We can fix this by just deleting the action attribute, as this means the form will post to then endpoint that loaded it - in this case /home.
Secondly, Flask sessions cannot be used without setting a secret key to encrypt the session. This can be done by assigning a value to app.secret_key, like so:
app = Flask(__name__)
app.secret_key = b"my_secret_key"
Finally, instead of passing the string to the template like so: render_template('page2.html', stringval = stringval), (note also that this should be stringval_get = stringval), you can access the session object directly from templates already. So, in all, we can change your application code to:
app.py:
from flask import Flask, render_template, request, session
app = Flask(__name__)
app.secret_key = b"my_secret_key"
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST' and 'stringval' in request.form:
session["stringvalue_topass"] = request.form.get('stringval')
return render_template('page2.html')
return render_template("home.html")
#app.route('/page2', methods=['GET', 'POST'])
def page2():
return render_template('page2.html')
And your templates to:
home.html:
<!doctype html>
<h1>Enter Value </h1>
<div class="main">
<form class="pure-form" method="POST">
stringval:<br>
<input type="text" name="stringval"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit!</button>
</form>
</div>
</body>
page2.html:
<!doctype html>
<h1>You have selected </h1>
<div class="main">
{% if 'stringvalue_topass' in session %}
<pre>
{% print(session["stringvalue_topass"]) %}
</pre>
{% endif %}
</div>
</body>

No validation on submit Flask

For some reason, form.validate_on_submit() does not return anything.
from flask import Flask
from flask_wtf import FlaskForm
from wtforms import StringField, DecimalField, validators
from flask import render_template
app = Flask(__name__)
app.config.update(dict(
SECRET_KEY="super awesome key"
))
class MyForm(FlaskForm):
name = StringField('Product name', [validators.InputRequired(), validators.Length(min=0, max=30)])
#app.route('/', methods=['GET', 'POST'])
def index():
form = MyForm()
if form.validate_on_submit():
return "Mission accomplished!"
return render_template('submit.html', form=form)
{% macro render_field(field) %}
<dt>{{ field.label }}
<dd>{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endmacro %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Add new grocery product</h1>
<p>Provide appropriate product details</p>
<form method="POST" action="/">
{{ form.csrf_token }}
{{ render_field(form.name.label) }} {{ form.name(size=20) }}<br>
<input type="submit" value="Go">
</form>
</body>
</html>
The app itself is supposed to gather user input in specific form and insert this via SQLAlchemy into database. Output is supposed to:
Return "Mission accomplished!" if validation succeeded
Return validation of which field failed and display error msg "This field is required" on the submit.html template
EDIT
Duo some success with the code, I make another edit to the question. It seems that macro isn't displaying error message for appropriate field if the validation fails.
I.E. if Field name is empty, macro should create and display error message ( This Field cannot be empty) by itself.
FINAL EDIT
I managed to find the solution. Submit.html template seems to cause the issue with macro if render_field looks like this:
{{ render_field(form.name.label) }}
instaed of this:
{{ render_field(form.name) }}
#This might help
from flask import Flask
from flask_wtf import FlaskForm
#from wtform import SubmitField
from wtforms import StringField, DecimalField, validators,SubmitField
from flask import render_template
app = Flask(__name__)
app.config.update(dict(
SECRET_KEY="super awesome key"
))
class MyForm(FlaskForm):
you need to make an edit to your validators like this
name = StringField('Product name', validators = [InputRequired(), , Length(min=0, max=30)])
#create submit option in your flask form
submit = SubmitField("Submit")
#app.route('/', methods=['GET', 'POST'])
def index():
form = MyForm()
if form.validate_on_submit():
return "Mission accomplished!"
return render_template('submit.html', form=form)

wtforms hidden field value

I am using WTForms, and I have a problem with hidden fields not returning values, whereas the docs say they should. Here's a simple example:
forms.py:
from wtforms import (Form, TextField, HiddenField)
class TestForm(Form):
fld1 = HiddenField("Field 1")
fld2 = TextField("Field 2")
experiment.html:
{% from "_formshelper.html" import render_field %}
<html>
<body>
<table>
<form method=post action="/exp">
{% for field in form %}
{{ render_field(field) }}
{% endfor %}
<input type=submit value="Post">
</form>
</table>
</body>
</html>
(render_field just puts the label, field and errors in td tags)
experiment.py:
from flask import Flask, request, render_template
from templates.forms import *
from introspection import *
app = Flask(\__name__)
app.config.from_object(\__name__)
db_session = loadSession()
#app.route('/exp', methods=['POST', 'GET'])
def terms():
mydata = db_session.query(Peter).one()
form = TestForm(request.form, mydata)
if request.method == 'POST' and form.validate():
return str(form.data)
return render_template('experiment.html', form = form)
if __name__ == '__main__':
app.run(debug = True)
mydata returns the only row from a table that has 2 fields, fld1 and fld2. fld1 is an integer autoincrement field. The form is populated with that data, so if I run experiment.py, when I submit the form I get:
{'fld2': u'blah blah blah', 'fld1': u'1'}
But if I change fld1 to HiddenField, when I hit submit, I get:
{'fld2': u'blah blah blah', 'fld1': u''}
What am I doing wrong?
I suspect your hidden field is either (1) not getting a value set, or (2) the render_field macro isn't building it correctly. If I had to bet, I'd say your "mydata" object doesn't have the values you expect.
I stripped your code down to the bare minimum, and this works for me. Note I am explicitly giving a value to both fields:
from flask import Flask, render_template, request
from wtforms import Form, TextField, HiddenField
app = Flask(__name__)
class TestForm(Form):
fld1 = HiddenField("Field 1")
fld2 = TextField("Field 2")
#app.route('/', methods=["POST", "GET"])
def index():
form = TestForm(request.values, fld1="foo", fld2="bar")
if request.method == 'POST' and form.validate():
return str(form.data)
return render_template('experiment.html', form = form)
if __name__ == '__main__':
app.run()
and
<html>
<body>
<table>
<form method=post action="/exp">
{% for field in form %}
{{field}}
{% endfor %}
<input type=submit value="Post">
</form>
</table>
</body>
</html>
This gives me {'fld2': u'bar', 'fld1': u'foo'} as I would expect.
Check that mydata has an attribute "fld1" and it has a value. I might set it explicitly like form = TestForm(request.values, obj=mydata) - it doesn't look like WTForms would care, but I've gotten burned by it being weirdly picky sometimes.
If that doesn't work for you, come back and post your HTML and what values mydata has.

Categories