Mensaje Flash

Las buenas aplicaciones e interfaces de usuario se basan en la retroalimentación. Si el usuario no recibe suficiente retroalimentación, probablemente terminará odiando la aplicación. Flask proporciona una forma muy sencilla de dar retroalimentación a un usuario con el sistema de parpadeo. El sistema de parpadeo básicamente hace posible grabar un mensaje al final de una solicitud y acceder a él la próxima solicitud y sólo la próxima solicitud. Esto se suele combinar con una plantilla de diseño que hace esto. Tenga en cuenta que los navegadores y a veces los servidores web imponen un límite en el tamaño de las cookies. Esto significa que si los mensajes son demasiado grandes para las cookies de sesión, el parpadeo de los mensajes falla silenciosamente.

Flash simple

Así que aquí está un ejemplo completo:

from flask import Flask, flash, redirect, render_template, \
     request, url_for

app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@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'] != 'secret':
            error = 'Invalid credentials'
        else:
            flash('You were successfully logged in')
            return redirect(url_for('index'))
    return render_template('login.html', error=error)

Y aquí está la plantilla layout.html que hace la magia:

<!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 %}

Aquí está la plantilla index.html que hereda de layout.html:

{% extends "layout.html" %}
{% block body %}
  <h1>Overview</h1>
  <p>Do you want to <a href="{{ url_for('login') }}">log in?</a>
{% endblock %}

Y aquí está la plantilla login.html que también hereda de layout.html:

{% extends "layout.html" %}
{% block body %}
  <h1>Login</h1>
  {% if error %}
    <p class=error><strong>Error:</strong> {{ error }}
  {% endif %}
  <form method=post>
    <dl>
      <dt>Username:
      <dd><input type=text name=username value="{{
          request.form.username }}">
      <dt>Password:
      <dd><input type=password name=password>
    </dl>
    <p><input type=submit value=Login>
  </form>
{% endblock %}

Flashing con categorías

Changelog

Nuevo en la versión 0.3.

También es posible proporcionar categorías cuando se parpadea un mensaje. La categoría por defecto si no se proporciona nada es 'message'. Se pueden utilizar categorías alternativas para dar al usuario una mejor respuesta. Por ejemplo, los mensajes de error podrían mostrarse con un fondo rojo.

Para emitir un mensaje con una categoría diferente, basta con utilizar el segundo argumento de la función flash():

flash('Invalid password provided', 'error')

Dentro de la plantilla tienes que decirle a la función get_flashed_messages() que también devuelva las categorías. El bucle se ve ligeramente diferente en esa situación entonces:

{% with messages = get_flashed_messages(with_categories=true) %}
  {% if messages %}
    <ul class=flashes>
    {% for category, message in messages %}
      <li class="{{ category }}">{{ message }}</li>
    {% endfor %}
    </ul>
  {% endif %}
{% endwith %}

Este es sólo un ejemplo de cómo representar estos mensajes intermitentes. También se puede utilizar la categoría para añadir un prefijo como <strong>Error:</strong> al mensaje.

Filtrado de mensajes flash

Changelog

Nuevo en la versión 0.9.

Opcionalmente puede pasar una lista de categorías que filtre los resultados de get_flashed_messages(). Esto es útil si desea renderizar cada categoría en un bloque separado.

{% with errors = get_flashed_messages(category_filter=["error"]) %}
{% if errors %}
<div class="alert-message block-message error">
  <a class="close" href="#">×</a>
  <ul>
    {%- for msg in errors %}
    <li>{{ msg }}</li>
    {% endfor -%}
  </ul>
</div>
{% endif %}
{% endwith %}