Construir

Mensajes flash en Flask: avisos al usuario tras una acción

Cómo mostrar avisos temporales en Flask (éxito, error, advertencia) después de enviar un formulario o hacer una acción, usando el sistema de mensajes flash integrado.

Cuando un usuario envía un formulario, borra algo o inicia sesión, necesita saber qué pasó: “guardado correctamente”, “credenciales incorrectas”, “ese correo ya existe”. Flask trae un sistema de mensajes flash justo para eso: avisos que aparecen una vez, tras una acción, y desaparecen. Aquí cómo usarlo bien.

Qué es un mensaje flash

Un mensaje flash es un aviso que guardas en una petición y se muestra en la siguiente. Es perfecto para el patrón “haces algo → te redirijo → te muestro el resultado”. El mensaje se guarda, sobrevive a la redirección, se muestra una vez, y se borra solo.

Para usarlo necesitas tener configurada la secret_key de tu app, porque los mensajes se guardan en la sesión:

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

app = Flask(__name__)
app.secret_key = "tu-clave-secreta"

Lanzar un mensaje

En la ruta que procesa la acción, usas flash():

@app.route("/guardar", methods=["POST"])
def guardar():
    nombre = request.form.get("nombre", "").strip()
    if not nombre:
        flash("El nombre no puede estar vacío", "error")
        return redirect(url_for("formulario"))

    # ...guardar...
    flash("Guardado correctamente", "exito")
    return redirect(url_for("formulario"))

Fíjate en el segundo argumento: "error", "exito". Es la categoría del mensaje, y es lo que te permite mostrar cada tipo con un color distinto (rojo para error, verde para éxito). No es obligatorio, pero es lo que hace útil el sistema.

Mostrar los mensajes en la plantilla

En tu plantilla HTML (normalmente en el layout base, para que aparezcan en todas las páginas), recuperas los mensajes con get_flashed_messages:

{% with mensajes = get_flashed_messages(with_categories=true) %}
  {% if mensajes %}
    {% for categoria, texto in mensajes %}
      <div class="aviso aviso-{{ categoria }}">{{ texto }}</div>
    {% endfor %}
  {% endif %}
{% endwith %}

El with_categories=true es la clave: hace que cada mensaje venga con su categoría, para poder poner class="aviso-error" o class="aviso-exito" y darle color con CSS. Sin eso, solo obtienes el texto, sin saber si es éxito o error.

Darles estilo

Un CSS mínimo para diferenciarlos visualmente:

.aviso { padding: 12px 16px; border-radius: 8px; margin-bottom: 1rem; }
.aviso-exito { background: #e6f4ea; color: #1e7e34; }
.aviso-error { background: #fbe9e7; color: #c62828; }
.aviso-advertencia { background: #fff8e1; color: #f57f17; }

Las categorías que uses en flash() deben coincidir con las clases de tu CSS. Si lanzas flash(texto, "exito"), necesitas .aviso-exito.

El detalle que confunde: se muestran una sola vez

La característica central de los mensajes flash, y lo que a veces desconcierta: se consumen al mostrarse. Una vez que get_flashed_messages los recupera, desaparecen. Si recargas la página, ya no están. Eso es exactamente lo que quieres —un aviso de “guardado” no debe quedarse para siempre—, pero si esperabas que persistiera, esa es la razón de que “se vaya solo”.

Por el mismo motivo, llama a get_flashed_messages una sola vez por página. Si lo pones dos veces en la misma plantilla, la segunda vez ya no habrá mensajes, porque la primera los consumió.

Por qué redirigir y no solo renderizar

Verás que en los ejemplos hacemos flash() y luego redirect(), en vez de render_template() directo. Hay una razón: si renderizas la misma página tras un POST, al recargar el navegador el usuario reenvía el formulario (el molesto “¿reenviar datos?”). Redirigir evita eso —es el patrón “Post/Redirect/Get”—, y los mensajes flash están diseñados justo para sobrevivir esa redirección. Por eso van tan bien juntos.

Resumen

  • flash(texto, categoria) lanza un aviso; la categoría permite colorearlo.
  • get_flashed_messages(with_categories=true) los recupera en la plantilla.
  • Ponlo en el layout base para que aparezcan en todo el sitio.
  • Se muestran una sola vez y desaparecen — llámalo una vez por página.
  • Combínalos con redirect() (patrón Post/Redirect/Get) para una buena experiencia.

Con esto tu app le habla al usuario: cada acción tiene su confirmación o su aviso de error, en vez de dejarlo adivinando si funcionó. Es un detalle pequeño que separa una app pulida de una confusa.


¿Quieres que los avisos se cierren solos tras unos segundos, o con un botón de cerrar? Escríbeme desde contacto y lo vemos.

← Más de Construir