Python Pyramid - Message Flashing



The mechanism of message flashing is used by web application frameworks to provide certain feedback to the user about his interaction with the application. The flashed messages are held in a queue by the session object.

Flash messaging mechanism makes it possible to create a message in one view and render it in a view function called next. As in the previous section, we must enable the session factory first to be able to handle the session. To add a message in the message queue, use flash() method of the session object.

request.session.flash('Hello World')

The session has pop_flash() and peek_flash() methods. The pop_flash() method removes the last added message from the queue. The peek_flash() method returns true if the queue has a message, false if it is empty.

Both these methods are used in a template web page to fetch one or messages from the queue and render it as a part of the response.

Message Flashing Example

The mechanism of message flashing is demonstrated by the example below. Here, the login() view code checks if it has been invoked by POST or GET method. If the method is GET, it renders the login form with username and password fields. The submitted form is submitted with POST method to the same URL.

When the POST method is detected, the view further checks the validity of the inputs and flashes appropriate messages to the session queue. These error flash messages are extracted by the login template itself, whereas after the success flash message is flashed, the client is redirected to the index() view to render the index template.

The two views in the application code are −

@view_config(route_name='login', renderer='templates/login.html')
def login(request):
   if request.method == 'POST':
   if request.POST['password']=='' or request.POST['username']=='':
      request.session.flash('User name and password is required')
      return HTTPFound(location=request.route_url('login'))
   if len(request.POST['password'])in range(1,9):
      request.session.flash('Weak password!')
   if request.POST['username']not in ['admin', 'manager', 'supervisor']:
      request.session.flash('successfully logged in!')
      return HTTPFound(location=request.route_url('index'))
   else:
      request.session.flash('Reserved user ID Forbidden!')
      return HTTPFound(location=request.route_url('login'))
   return {}
   
@view_config(route_name='index', renderer='templates/index.html')
def index(request):
   return {}

The login.html template has the following code −

<!doctype html>
<html>
<head>
   <style>
      p {background-color:grey; font-size: 150%}
   </style>
</head>
<body>
   <h1>Pyramid Message Flashing Example</h1>
   {% if request.session.peek_flash()%}
      <div id="flash">
         {% for message in request.session.pop_flash() %}
         <p>{{ message }}</p>
         {% endfor %}
      </div>
   {% endif %}
   <h3>Login Form</h3>
   <form action="" method="POST">
      <dl>
         <dt>Username:
            <dd><input type="text" name="username">
         <dt>Password:
         <dd><input type="password" name="password">
      </dl>
      <input type="submit" value="Login">
   </form>
</body>
</html>

Before the login form is displayed, the jinja2 template code traverses through the message queue, pops each message in the <div id='flash'> section.

Following is the script for index.html that flashes the success messages inserted by the login() view −

<!doctype html>
<html>
<head>
   <style>
      p {background-color:grey; font-size: 150%}
   </style>
</head>
<body>
   {% if request.session.peek_flash()%}
   <div id="flash">
   {% for message in request.session.pop_flash() %}
   <p>{{ message }}</p>
   {% endfor %}
   {% endif %}
   <h1>Pyramid Message Flashing Example</h1>
   <h3>Do you want to <a href = "/login">
   <b>log in?</b></a></h3>
</body>
</html>

Example

The application code for this example is main.py

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
from pyramid.session import SignedCookieSessionFactory
from pyramid.httpexceptions import HTTPFound

my_session_factory = SignedCookieSessionFactory(' abcQWE123!@#')
@view_config(route_name='login', renderer='templates/login.html')
def login(request):
   if request.method == 'POST':
      if request.POST['password']=='' or  request.POST['username']=='':
      request.session.flash('User name and password is required')
      return HTTPFound(location=request.route_url('login'))
   if len(request.POST['password'])in range(1,9):
      request.session.flash('Weak password!')
   if request.POST['username']not in ['admin', 'manager', 'supervisor']:
      request.session.flash('successfully logged in!')
      return HTTPFound(location=request.route_url('index'))
   else:
      request.session.flash('Reserved user ID Forbidden!')
      return HTTPFound(location=request.route_url('login'))
   return {}
   
@view_config(route_name='index', renderer='templates/index.html')
def index(request):
   return {}
   
if __name__ == '__main__':
   with Configurator() as config:
      config.set_session_factory(my_session_factory)
      config.include('pyramid_jinja2')
      config.add_jinja2_renderer(".html")
      config.add_route('login','/login')
      config.add_route('index','/')
      config.scan('flash')
      app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

Save this program code as app.py in a flash subfolder in the virtual environment for Pyramid, putting a blank __init__.py in it. Store the two templates ("index.html" and "login.html") in flush\templates folder.

Output

Run the main.py and open the login form in the browser by clicking the http://localhost:6543/login link.

Pyramid Message

Try entering one of the reserved usernames 'admin', 'manager', or 'supervisor'. The error message will be flashed as shown below −

Weak Password

This time, enter acceptable credentials and see the result −

Loggedin
Advertisements