Use of with for getting flashed messages in flask [duplicate] - python

This question already has answers here:
How does the 'with' statement work in Flask (Jinja2)?
(2 answers)
Closed 4 years ago.
I was checking the message flashing in flask framework from here.
This is a basic example where a template file (Index.html) is used to provide the initial link and another template file (Login.html) creates the form.
The files are:
Login.html:
<!doctype html>
<html>
<body>
<h1>Login</h1>
{% if error %}
<p><strong>Error:</strong> {{ error }}
{% endif %}
<form action = "" method = post>
<dl>
<dt>Username:</dt>
<dd>
<input type = text name = username
value = "{{request.form.username }}">
</dd>
<dt>Password:</dt>
<dd><input type = password name = password></dd>
</dl>
<p><input type = submit value = Login></p>
</form>
</body>
</html>
Index.html:
<!doctype html>
<html>
<head>
<title>Flask Message flashing</title>
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li<{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<h1>Flask Message Flashing Example</h1>
<p>Do you want to <a href = "{{ url_for('login') }}">
<b>log in?</b></a></p>
</body>
</html>
Flash.py:
from flask import Flask, flash, redirect, render_template, request, url_for
app = Flask(__name__)
app.secret_key = 'random string'
#app.route('/')
def index():
return render_template('index.html')
#app.route('/login', methods = ['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or \
request.form['password'] != 'admin':
error = 'Invalid username or password. Please try again!'
else:
flash('You were successfully logged in')
return redirect(url_for('index'))
return render_template('login.html', error = error)
if __name__ == "__main__":
app.run(debug = True)
The part that is confusing me is inside index.html. It's using with messages = get_flashed_messages() to get the messages from the session. I do not fully understand why it's using with? I know with is used for resources, files, streams etc to control the closing procedure (and for not leaving something open when something goes wrong etc). What's the resource it's accessing using with in this context?
I tried removing it (in this context) and an error occurred:
jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag
'messages'.
Also, example use cases from programcreek.com does not use with with get_flashed_messages so what's the case here?

Jinja templates are not Python. with in a template is not a Python context manager, it just introduces a new scope; this code definesa new variable messages that is only visible until the endwith.
See the docs.

try to fix index.html
<!doctype html>
<html>
<head>
<title>Flask Message flashing</title>
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<h1>Flask Message Flashing Example</h1>
<p>Do you want to <a href="{{ url_for('login') }}">
<b>log in?</b></a></p>
</body>
</html>

Related

How to show a modal notification using flask framework and python?

I am working on building a web application using Flask framework and Python.
Using one of the html pages, i am getting inputs from the user and processing them once the user clicks on the Submit button. The requirement is that, once the user clicks on the Submit button, i would like to show a modal notification (or any notification) that the data is being processed.
The code for the Submit button in process_data.html is -
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
I tried adding modal code to it as follows -
<div class="form-group">
{{ form.submit(class="btn btn-outline-info", data-toggle="modal", data-target="#exampleModal") }}
</div>
but it failed with jinja2.exceptions.TemplateSyntaxError: invalid syntax for function call expression.
routes.py code -
#app.route("/process_data", methods=['GET','POST'])
def process_data():
form = ProcessDataForm()
if form.validate_on_submit():
posts = get_data('process_data', version=form.version.data, cn=form.cn.data, ip=form.ip.data)
if posts:
flash(f'Processing Complete!','success')
else:
flash(f'Processing failed','warning')
return render_template('process_data.html', title='Process Data', form=form, posts=posts)
return render_template('process_data.html', title='Process Data', form=form)
Can someone please help? Thanks!
You can do it using Message Flash.
A sample code is provided here:
from flask import flash
#app.route("/process_data", methods=['GET','POST'])
def process_data():
form = ProcessDataForm()
if form.validate_on_submit():
flash('Data is being processed')
posts = get_data('process_data', version=form.version.data, cn=form.cn.data, ip=form.ip.data)
return render_template('process_data.html', title='Process Data', form=form, posts=posts)
return render_template('process_data.html', title='Process Data', form=form)
In you html :
<!doctype html>
<title>My Application</title>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
Please find the documentation for more explaination.

Flask submit form on POST: '405 Method not allowed'

Hi I am a bit confused about a flask application. I have a route / to welcomepage that generates a ux_uuid then passes it to the form. Now, after I submit the form I want the ID (ux_uuid) passed on as well. However, in all cases (form.validate==false or even if all is ok) it ends up in a 405 error - Method not allowed. The methods=['GET','POST'] has the ['POST'] method is there so I don't understand why even if request.method == 'POST' breaks?
app.py:
import logging, os
from flask import Flask, json, make_response, render_template, request, session, redirect, url_for, jsonify
from ux.forms import QuestionForm
from flask_wtf.csrf import CSRFProtect
import sqlite3
app = Flask(__name__, static_url_path='')
app.secret_key = "NSA secret key"
csrf = CSRFProtect()
csrf.init_app(app)
#app.route('/', methods=['GET', 'POST'])
def welcomepage():
# Here is the random user ID generated by some random function but
# can be set to some string to test:
ux_uuid = 'TETST_ID' #or set this to ux_uuid='TestUserID'
return render_template('welcomepage.html', ux_uuid=ux_uuid)
#app.route('/form1/<ux_uuid>', methods=['GET', 'POST'])
def form1(ux_uuid):
form = QuestionForm()
if request.method == 'POST':
if form.validate() == False:
print("VALIDATE ME !")
return render_template('/form1.html/<ux_uuid>', form=form, ux_uuid=ux_uuid)
else:
#
#mylist = json.dumps(form.first_question)
print('I STORED ALL THE FORM DATA IN THE SQLITE3 DB here - and GO ON TO:')
return render_template('signup.html', ux_uuid=ux_uuid)
elif request.method == 'GET':
return render_template('form1.html', form=form, ux_uuid=ux_uuid)
return render_template('form1.html')
# turn on debug=true to see error messages
if __name__ == "__main__":
app.run(debug=True)
This is the /ux/forms.py:
from flask_wtf import Form
from wtforms import SelectMultipleField, SubmitField, RadioField
from wtforms.validators import DataRequired, Email, Length
class QuestionForm(Form):
first_question = SelectMultipleField('What is your favourite food? Select all that apply:', choices=[('pizza','pizza'), ('more pizza', 'more pizza'), ('burger', 'burger'), ('salad', 'salad'), ('fries', 'fries'), ('pasta', 'pasta')], validators=[DataRequired()])
second_question = RadioField('How many coins do you have?', choices=[('0','0'), ('1-5','1-5'), ('5-10','5-20'), ('More than 20', 'More than 20')], validators=[DataRequired()])
third_question = RadioField('Do you like chocolate?', choices=[('Yes', 'Yes'), ('No', 'No')], validators=[DataRequired()])
submit = SubmitField('Submit & Continue')
and the form1.html:
<!DOCTYPE html>
<html>
<head>
<title>PREVIOUS EXPERIENCE</title>
</head>
<body>
<main class="container signup-section">
<div class="section-content">
<h2>Please Answer the following questions</h2>
<form method="POST" action="/form1">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.first_question.label }}
{% if form.first_question.errors %}
{% for error in form.first_question.errors %}
<p class="error-message">{{ error }}</p>
{% endfor %}
{% endif %}
{{ form.first_question }}
</div>
<div class="form-group">
{{ form.second_question.label }}
{% if form.second_question.errors %}
{% for error in form.second_question.errors %}
<p class="error-message">{{ error }}</p>
{% endfor %}
{% endif %}
{{ form.second_question }}
</div>
<div class="form-group">
{{ form.third_question.label }}
{% if form.third_question.errors %}
{% for error in form.third_question.errors %}
<p class="error-message">{{ error }}</p>
{% endfor %}
{% endif %}
{{ form.third_question }}
</div>
{{ form.submit(class="btn-primary") }}
</form>
</div>
<p>ID TEST:</p>
{{ ux_uuid }}
</main>
</body>
</html>
and the welcomepage:
<!DOCTYPE html>
<html>
<head>
<title>WELCOMEPAGE</title>
</head>
<body><p> ENTRY PAGE / START WELCOME </p>
Continue</body>
</html>
Here are all files to test: stack.zip

How to handle a variable in HTML?

I have the following flask application that displays a dashboard with various buttons. Each button executes a python function. After the execution of such a function I want the application to return to the dashboard. In order to give the user a simple log I want to output some string on the html page. For that thought about a tag above the buttons on the dashboard that get filled with the respective value. How can I do that?
Flask:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def main():
return render_template('index.html')
#app.route('/something')
def do_something():
print("Hello")
return render_template('index.html', user="Successfully executed!")
if __name__ == "__main__":
app.run()
HTML:
<!DOCTYPE html>
<html>
<head>
<head>
<meta charset="UTF-8">
</head>
<title>MP Reporting</title>
</head>
<body>
<div value=user></div>
Your button
</body>
</html>
For flask template use "{{kwarg}}" i.e. in your example
<div>{{user}}</div>
will render as
<div>Successfully executed!</div>
In addition to other answers, I suggest using Flask's built-in message flashing which is simpler, and neater instead of passing variables to render_template manually. It's simple as that:
(template)
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div>{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
(flask view)
from flask import flash
flash("Successfully executed!")
You can get more information from here.
You can print variables using Jinja2.
To print out the variable user in your example add
{{ user }} in the html template.
If you send a list of items to the html you can output them by using a simple for:
{% for item in items %}
{{ item }}
{% endfor %}

Flask: Why am I getting a 404 error?

I'm brushing up on my Flask skills to make a "Jeopardy score keeper" application. What I'm trying to do right now is to take a player's score from a database and display it on the screen. I keep getting a "404 NOT FOUND" error. Here's my code:
JeopardyApp.py
#app.route('/layout', methods=['POST'])
def layout():
db = get_db()
try:
cur1 = db.execute('SELECT score FROM {tn} where name="Tyler"'.format(tn="Score"))
score1 = cur1.fetchone()
except:
flash("This person doesn't exist in our database!")
return render_template('layout.html', score=score1)
layout.html
<!doctype html>
<title>JeopardyApp</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
<h1>Jeopardy Score Keeper</h1>
<div class=metanav>
<p>Currently under construction...</p>
</div>
<div>
<p>Tyler</p>
<tr><td>{{ score.score }}</td></tr>
</div>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>
Any help is appreciated. Thank you.
The route you've set for the layout function is only reachable via the POST method.
By default, your webbrowser uses the GET method.
Change your route this way:
#app.route('/layout', methods=['GET'])

Flask & WTForms: How to make a form with multiple submit buttons? [duplicate]

This question already has answers here:
Determine which WTForms button was pressed in a Flask view
(1 answer)
Validate WTForm form based on clicked button
(1 answer)
Closed 6 years ago.
Imagine I need to build a travel planning form like this:
Going from [_Picadily_Circus____]
Going to [_Marylebone_____]
(Starting by) (Arriving by) [5]:[30][pm]
Both (Starting by) (Arriving by) are submit buttons. The example is artificial to show a two-button usecase so let's not discuss usability.
How do I do this with Flask and WTForms?
How to see which button was actually pressed?
Your form's submit button's data value will be True if it was pressed. See very simple example below of a form with two submit buttons and a single input field.
from flask import Flask, render_template, flash
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'well-secret-password'
class MyForm(Form):
name = StringField(label='Name', validators=[DataRequired()])
starting = SubmitField(label='Starting')
ending = SubmitField(label='Ending')
#app.route('/', methods=['GET', 'POST'])
def index():
form = MyForm()
if form.validate_on_submit():
print "Starting data Value : {value}".format(value=form.starting.data)
print "Ending data Value : {value}".format(value=form.ending.data)
flash(
"You submitted name {name} via button {button}".format(
name=form.name.data,
button="Starting" if form.starting.data else "Ending"
)
)
return render_template('index.html', form=form)
if form.errors:
for error_field, error_message in form.errors.iteritems():
flash("Field : {field}; error : {error}".format(field=error_field, error=error_message))
return render_template('index.html', form=form)
if __name__ == '__main__':
app.run(debug=True)
Here's the template file index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<form method="POST" action="{{ url_for('index') }}">
{{ form.csrf_token }}
{{ form.name.label }} {{ form.name(size=20) }}
<br><br>
{{ form.starting }}
{{ form.ending }}
</form>
</body>
</html>

Categories