Los mensajes de notificación se utilizan comúnmente en aplicaciones web para mostrar un mensaje de notificación temporal (también conocido como «mensaje flash») al usuario después de procesar una forma o otros tipos de entrada del usuario.
Django proporciona plena compatibilidad con mensajería basada en cookies y sesiones, tanto para usuarios anónimos como autenticados. El marco de mensajes permite almacenar temporalmente mensajes en una solicitud y recuperarlos para su visualización en una solicitud posterior (generalmente la siguiente). Cada mensaje está etiquetado con un nivel específico que determina su prioridad (por ejemplo, info, warning o error).
Los mensajes se implementan a través de una clase middleware y el procesador de contexto correspondiente context processor.
La configuración por defecto settings.py creada por django-admin startproject ya contiene todas las configuraciones necesarias para habilitar la funcionalidad de mensajes:
'django.contrib.messages' está en INSTALLED_APPS.
MIDDLEWARE contiene 'django.contrib.sessions.middleware.SessionMiddleware' y 'django.contrib.messages.middleware.MessageMiddleware'.
La configuración por defecto del almacenamiento de mensajes <message-storage-backends> se basa en sesiones. Por lo tanto, SessionMiddleware debe estar habilitado y aparecer antes que MessageMiddleware en MIDDLEWARE.
La opción 'context_processors' del backend de plantillas Django definido en tu configuración TEMPLATES contiene 'django.contrib.messages.context_processors.messages'.
Si no deseas utilizar mensajes, puedes eliminar 'django.contrib.messages' de tus INSTALLED_APPS, la línea MessageMiddleware de MIDDLEWARE y el procesador de contexto messages de TEMPLATES.
El marco de mensajes puede utilizar diferentes backends para almacenar mensajes temporales.
Django proporciona tres clases de almacenamiento integradas en django.contrib.messages:
Esta clase almacena todos los mensajes dentro de la sesión del request. Por lo tanto, requiere la aplicación contrib.sessions de Django.
Esta clase almacena los datos de mensaje en una cookie (firmada con un hash secreto para prevenir manipulación) para persistir las notificaciones a través de solicitudes. Los mensajes antiguos se eliminan si el tamaño de los datos de la cookie superaría 2048 bytes.
Esta clase utiliza primero CookieStorage, y cae en SessionStorage para los mensajes que no caben en una sola cookie. También requiere la aplicación contrib.sessions de Django.
Este comportamiento evita escribir en la sesión siempre que sea posible. Debería proporcionar el mejor rendimiento en el caso general.
FallbackStorage es la clase de almacenamiento por defecto. Si no le conviene a tus necesidades, puedes seleccionar otra clase de almacenamiento estableciendo MESSAGE_STORAGE a su importación completa, por ejemplo:
MESSAGE_STORAGE = "django.contrib.messages.storage.cookie.CookieStorage"
Para crear tu propia clase de almacenamiento, hereda la clase BaseStorage en django.contrib.messages.storage.base y implementa los métodos _get y _store.
El marco de trabajo de los mensajes se basa en una arquitectura de nivel configurable similar a la del módulo de registro de Python. Los niveles de mensaje permiten agrupar mensajes por tipo para que puedan ser filtrados o mostrados de manera diferente en vistas y plantillas.
Los niveles integrados, que se pueden importar directamente desde django.contrib.messages, son:
Constante |
Propósito |
|---|---|
|
Mensajes relacionados con el desarrollo que serán ignorados (o eliminados) en una implementación de producción |
|
Mensajes informativos para el usuario |
|
Una acción fue exitosa, por ejemplo: «Tu perfil se actualizó con éxito» |
|
No ocurrió un error pero puede ser inminente |
|
Una acción no fue exitosa o ocurrió otro tipo de error |
La configuración MESSAGE_LEVEL se puede utilizar para cambiar el nivel mínimo registrado (o se puede cambiar por solicitud _). Los intentos de agregar mensajes de un nivel inferior a este serán ignorados.
Para agregar un mensaje, llame a:
from django.contrib import messages
messages.add_message(request, messages.INFO, "Hello world.")
Algunos métodos de atajo proporcionan una forma estándar de agregar mensajes con etiquetas comúnmente utilizadas (que suelen representarse como clases HTML para el mensaje):
messages.debug(request, "%s SQL statements were executed." % count)
messages.info(request, "Three credits remain in your account.")
messages.success(request, "Profile details updated.")
messages.warning(request, "Your account expires in three days.")
messages.error(request, "Document deleted.")
En tu plantilla, utiliza algo como:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
Si estás utilizando el procesador de contexto, asegúrate de que la plantilla se renderice con un RequestContext. De lo contrario, asegúrate de que messages esté disponible en el contexto de la plantilla.
Incluso si sabes que solo hay un mensaje, debes seguir iterando sobre la secuencia messages, porque de otra manera no se eliminará el almacenamiento de mensajes para la siguiente solicitud.
El procesador de contexto también proporciona una variable DEFAULT_MESSAGE_LEVELS que es un mapeo de los nombres de nivel de mensaje a su valor numérico:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %}
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
Fuera de las plantillas, puedes utilizar get_messages():
from django.contrib.messages import get_messages
storage = get_messages(request)
for message in storage:
do_something_with_the_message(message)
Por ejemplo, puedes obtener todos los mensajes para devolverlos en una JSONResponseMixin en lugar de una TemplateResponseMixin.
get_messages() devolverá una instancia del backend de almacenamiento configurado.
Message¶Cuando iteras sobre la lista de mensajes en una plantilla, lo que obtienes son instancias de la clase Message. Solo tienen unos pocos atributos:
message: El texto real del mensaje.
level: Un entero que describe el tipo de mensaje (consulte la sección sobre niveles de mensajes arriba).
tags: Una cadena combinando todos los etiquetas del mensaje (extra_tags y level_tag) separadas por espacios.
extra_tags: Una cadena que contiene etiquetas personalizadas para este mensaje, separadas por espacios. Está vacía por defecto.
level_tag: La representación en cadena del nivel. Por defecto, es la versión minúscula del nombre de la constante asociada, pero esto se puede cambiar si es necesario mediante el MESSAGE_TAGS ajuste.
Los niveles de mensajes son nada más que enteros, por lo que puedes definir tus propios constantes de nivel y utilizarlas para crear retroalimentación del usuario más personalizada, p. ej.:
CRITICAL = 50
def my_view(request):
messages.add_message(request, CRITICAL, "A serious error occurred.")
Cuando se crean niveles de mensajes personalizados debes tener cuidado al evitar sobrecargar los niveles existentes. Los valores para los niveles integrados son:
Nivel Constante |
Valor |
|---|---|
|
10 |
|
20 |
|
25 |
|
30 |
|
40 |
Si necesitas identificar los niveles personalizados en tu HTML o CSS, debes proporcionar una mapeación a través de la configuración MESSAGE_TAGS.
Nota
Si estás creando una aplicación reutilizable, se recomienda utilizar solo los niveles message integrados y no confiar en ningún nivel personalizado.
El nivel mínimo registrado puede establecerse por solicitud a través del método set_level:
from django.contrib import messages
# Change the messages level to ensure the debug message is added.
messages.set_level(request, messages.DEBUG)
messages.debug(request, "Test message...")
# In another request, record only messages with a level of WARNING and higher
messages.set_level(request, messages.WARNING)
messages.success(request, "Your profile was updated.") # ignored
messages.warning(request, "Your account is about to expire.") # recorded
# Set the messages level back to default.
messages.set_level(request, None)
De manera similar, se puede recuperar el nivel efectivo actual con get_level:
from django.contrib import messages
current_level = messages.get_level(request)
Para obtener más información sobre cómo funcionan los niveles de mensajes, consulta Niveles de mensaje arriba.
Si estás escribiendo una aplicación reutilizable (o otra pieza de código) y quieres incluir funcionalidad de mensajería, pero no quieres requerir a tus usuarios que la habiliten si no lo quieren, puedes pasar un argumento de palabra clave adicional fail_silently=True a cualquier de los métodos de la familia add_message. Por ejemplo:
messages.add_message(
request,
messages.SUCCESS,
"Profile details updated.",
fail_silently=True,
)
messages.info(request, "Hello world.", fail_silently=True)
Nota
Establecer fail_silently=True solo oculta el MessageFailure que de otro modo ocurriría cuando el marco de mensajes está deshabilitado y se intenta usar uno de los métodos de la familia add_message. No oculta fallas que puedan ocurrir por otras razones.
Agrega un atributo de mensaje de éxito a las clases basadas en FormView
cleaned_data es los datos limpios del formulario que se utilizan para la formateación de cadenas
**Ejemplo views.py:
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreateView(SuccessMessageMixin, CreateView):
model = Author
success_url = "/success/"
success_message = "%(name)s was created successfully"
Los datos limpios del form están disponibles para la interpolación de cadenas utilizando el sintaxis %(field_name)s. Para ModelForms, si necesitas acceso a campos desde el objeto guardado, sobreescribe el método get_success_message().
**Vistas.py de ejemplo para ModelForms:
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import ComplicatedModel
class ComplicatedCreateView(SuccessMessageMixin, CreateView):
model = ComplicatedModel
success_url = "/success/"
success_message = "%(calculated_field)s was created successfully"
def get_success_message(self, cleaned_data):
return self.success_message % dict(
cleaned_data,
calculated_field=self.object.calculated_field,
)
Los mensajes están marcados para ser eliminados cuando se itera la instancia de almacenamiento (y se eliminan al procesar la respuesta).
Para evitar que los mensajes sean eliminados, puedes establecer el almacenamiento de mensajes en False después de iterar:
storage = messages.get_messages(request)
for message in storage:
do_something_with(message)
storage.used = False
Debido a la forma en que funcionan las cookies (y por lo tanto las sesiones), el comportamiento de cualquier backend que utilice cookies o sesiones es indefinido cuando el mismo cliente realiza múltiples solicitudes que establecen o recuperan mensajes en paralelo. Por ejemplo, si un cliente inicia una solicitud que crea un mensaje en una ventana (o pestaña) y luego otra que recupera cualquier mensaje no iterado en otra ventana, antes de que la primera ventana redirija, el mensaje puede aparecer en la segunda ventana en lugar de la primera ventana donde se espera.
En resumen, cuando están involucradas múltiples solicitudes simultáneas del mismo cliente, los mensajes no se garantizan para ser entregados a la misma ventana que los creó ni, en algunos casos, en absoluto. Ten en cuenta que esto suele no ser un problema en la mayoría de las aplicaciones y se convertirá en un asunto sin importancia en HTML5, donde cada ventana/pestaña tendrá su propio contexto de navegación.
Un par de configuraciones te dan control sobre el comportamiento de los mensajes:
NIVEL_DE_MENSAJE
ALMACÉN_DE_MENSAJES
ETIQUETAS_DE_MENSAJES
Los textos traducidos son:
DOMINIO_DE_COOKIE_DE_SESION
COOKIE_DE_SESION_SEGURA
HTTPONLY_COOKIE_DE_SESION
Este módulo ofrece un método de aserción de prueba personalizado, para probar mensajes asociados a una HttpResponse.
Para aprovechar esta aserción, agrega MessagesTestMixin a la jerarquía de clases:
from django.contrib.messages.test import MessagesTestMixin
from django.test import TestCase
class MsgTestCase(MessagesTestMixin, TestCase):
pass
Luego, hereda de MsgTestCase en tus pruebas.
Aserta que los mensajes messages agregados a la respuesta coinciden con expected_messages.
expected_messages es una lista de objetos Message.
Por defecto, la comparación es dependiente de la ordenación. Puedes deshabilitar esto estableciendo el argumento ordered a False.
may 31, 2026