Con mucha frecuencia en las aplicaciones web, es necesario mostrar un mensaje de notificación por única vez (también conocido como “mensaje flash”) al usuario después de procesar un formulario o algunos otros tipos de entrada del usuario.
Para esto, Django proporciona soporte completo para mensajes basados en cookies y sesiones, tanto para usuarios anónimos como autenticados. El marco de mensajes le permite almacenar mensajes temporalmente en una solicitud y recuperarlos para mostrarlos en una solicitud posterior (generalmente la siguiente). Cada mensaje está etiquetado con un level
que determina su prioridad (p. ej., info
, warning
, o error
).
Habilitación de mensajes
Los mensajes se implementan a través de un middleware clase y correspondiente procesador de contexto.
El valor por defecto settings.py
creado por django-admin startproject
ya contiene todas las configuraciones necesarias para habilitar la funcionalidad de mensajes:
-
'django.contrib.messages'
es enINSTALLED_APPS
. -
MIDDLEWARE
contiene'django.contrib.sessions.middleware.SessionMiddleware'
y'django.contrib.messages.middleware.MessageMiddleware'
.El valor por defecto backend de almacenamiento se basa en sesiones. Es por eso
SessionMiddleware
debe estar habilitado y aparecer antesMessageMiddleware
enMIDDLEWARE
. - los
'context_processors'
opción de laDjangoTemplates
backend definido en tuTEMPLATES
el ajuste contiene'django.contrib.messages.context_processors.messages'
.
Si no desea utilizar mensajes, puede eliminar 'django.contrib.messages'
de tu INSTALLED_APPS
, los MessageMiddleware
línea de MIDDLEWARE
, y el messages
procesador de contexto de TEMPLATES
.
Configurar el motor de mensajes
Backends de almacenamiento
El marco de mensajes puede usar diferentes backends para almacenar mensajes temporales.
Django proporciona tres clases de almacenamiento integradas en django.contrib.messages
:
-
class storage.session.SessionStorage
-
Esta clase almacena todos los mensajes dentro de la sesión de la solicitud. Por lo tanto, requiere de Django
contrib.sessions
solicitud.
-
class storage.cookie.CookieStorage
-
Esta clase almacena los datos del mensaje en una cookie (firmada con un hash secreto para evitar la manipulación) para conservar las notificaciones entre las solicitudes. Los mensajes antiguos se descartan si el tamaño de los datos de la cookie excede los 2048 bytes.
Cambiado en Django 3.2:
El formato de los mensajes se cambió al RFC 6265 formato compatible.
-
class storage.fallback.FallbackStorage
-
Esta clase utiliza por primera vez
CookieStorage
y vuelve a usarSessionStorage
para los mensajes que no caben en una sola cookie. También requiere de Djangocontrib.sessions
solicitud.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 predeterminada. Si no es adecuado para sus necesidades, puede seleccionar otra clase de almacenamiento configurando MESSAGE_STORAGE
a su ruta de importación completa, por ejemplo:
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
-
class storage.base.BaseStorage
Para escribir su propia clase de almacenamiento, subclase el BaseStorage
clase en django.contrib.messages.storage.base
e implementar el _get
y _store
métodos.
Niveles de mensaje
El marco de mensajes se basa en una arquitectura de nivel configurable similar a la del módulo de registro de Python. Los niveles de mensaje le permiten agrupar mensajes por tipo para que se puedan filtrar o mostrar de manera diferente en vistas y plantillas.
Los niveles integrados, que se pueden importar desde django.contrib.messages
directamente, son:
Constante | Objetivo |
---|---|
DEBUG |
Mensajes relacionados con el desarrollo que se ignorarán (o eliminarán) en una implementación de producción |
INFO |
Mensajes informativos para el usuario |
SUCCESS |
Una acción se realizó correctamente, por ejemplo, “Su perfil se actualizó correctamente”. |
WARNING |
No se produjo una falla, pero puede ser inminente |
ERROR |
Una acción fue no exitoso o se produjo algún otro error |
los MESSAGE_LEVEL
La configuración se puede utilizar para cambiar el nivel mínimo registrado (o se puede cambiar por solicitud). Se ignorarán los intentos de agregar mensajes de un nivel inferior a este.
Etiquetas de mensaje
Las etiquetas de mensaje son una representación de cadena del nivel del mensaje más cualquier etiqueta adicional que se haya agregado directamente en la vista (consulte Agregar etiquetas de mensaje adicionales a continuación para obtener más detalles). Las etiquetas se almacenan en una cadena y están separadas por espacios. Normalmente, las etiquetas de mensaje se utilizan como clases CSS para personalizar el estilo del mensaje según el tipo de mensaje. De forma predeterminada, cada nivel tiene una sola etiqueta que es una versión en minúsculas de su propia constante:
Constante de nivel | Etiqueta |
---|---|
DEBUG |
debug |
INFO |
info |
SUCCESS |
success |
WARNING |
warning |
ERROR |
error |
Para cambiar las etiquetas predeterminadas para un nivel de mensaje (ya sea integrado o personalizado), configure el MESSAGE_TAGS
ajuste a un diccionario que contiene los niveles que desea cambiar. Como esto amplía las etiquetas predeterminadas, solo necesita proporcionar etiquetas para los niveles que desea anular:
from django.contrib.messages import constants as messages MESSAGE_TAGS = { messages.INFO: '', 50: 'critical', }
Usar mensajes en vistas y plantillas
-
add_message(request, level, message, extra_tags="", fail_silently=False)
Agregar un mensaje
Para agregar un mensaje, llame al:
from django.contrib import messages messages.add_message(request, messages.INFO, 'Hello world.')
Algunos métodos de acceso directo proporcionan una forma estándar de agregar mensajes con etiquetas de uso común (que generalmente se representan 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.')
Visualización de mensajes
-
get_messages(request)
En tu plantilla, usa 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á utilizando el procesador de contexto, su plantilla debe renderizarse con un RequestContext
. De lo contrario, asegúrese messages
está disponible para el contexto de la plantilla.
Incluso si sabe que solo hay un mensaje, debe repetir el messages
secuencia, porque de lo contrario el almacenamiento de mensajes no se borrará para la siguiente solicitud.
El procesador de contexto también proporciona un DEFAULT_MESSAGE_LEVELS
variable que es una asignación 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 usar 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, puede recuperar todos los mensajes para devolverlos en un JSONResponseMixin en lugar de un TemplateResponseMixin
.
get_messages()
devolverá una instancia del backend de almacenamiento configurado.
los Message
clase
-
class storage.base.Message
-
Cuando recorre la lista de mensajes en una plantilla, lo que obtiene son instancias del
Message
clase. Tienen solo algunos atributos:-
message
: El texto real del mensaje. -
level
: Un número entero que describe el tipo de mensaje (consulte la sección de niveles de mensaje más arriba). -
tags
: Una cadena que combina todas las etiquetas del mensaje (extra_tags
ylevel_tag
) separados por espacios. -
extra_tags
: Una cadena que contiene etiquetas personalizadas para este mensaje, separadas por espacios. Está vacío por defecto. -
level_tag
: La representación de cadena del nivel. De forma predeterminada, es la versión en minúsculas del nombre de la constante asociada, pero esto se puede cambiar si lo necesita utilizando elMESSAGE_TAGS
configuración.
-
Crear niveles de mensajes personalizados
Los niveles de los mensajes no son más que números enteros, por lo que puede definir sus propias constantes de nivel y usarlas para crear comentarios de usuario más personalizados, por ejemplo:
CRITICAL = 50 def my_view(request): messages.add_message(request, CRITICAL, 'A serious error occurred.')
Al crear niveles de mensajes personalizados, debe tener cuidado de no sobrecargar los niveles existentes. Los valores de los niveles integrados son:
Constante de nivel | Valor |
---|---|
DEBUG |
10 |
INFO |
20 |
SUCCESS |
25 |
WARNING |
30 |
ERROR |
40 |
Si necesita identificar los niveles personalizados en su HTML o CSS, debe proporcionar un mapeo a través del MESSAGE_TAGS
configuración.
Nota
Si está creando una aplicación reutilizable, se recomienda utilizar solo los niveles de mensajes integrados y no depender de ningún nivel personalizado.
Cambiar el nivel mínimo registrado por solicitud
El nivel mínimo registrado se puede configurar por solicitud a través del set_level
método:
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)
Del mismo modo, el nivel efectivo actual se puede recuperar con get_level
:
from django.contrib import messages current_level = messages.get_level(request)
Para obtener más información sobre cómo funciona el nivel mínimo registrado, consulte Niveles de mensaje más arriba.
Agregar etiquetas de mensaje adicionales
Para un control más directo sobre las etiquetas de los mensajes, opcionalmente puede proporcionar una cadena que contenga etiquetas adicionales a cualquiera de los métodos de adición:
messages.add_message(request, messages.INFO, 'Over 9000!', extra_tags='dragonball') messages.error(request, 'Email box full', extra_tags='email')
Las etiquetas adicionales se agregan antes de la etiqueta predeterminada para ese nivel y están separadas por espacios.
Fallar silenciosamente cuando el marco de mensajes está deshabilitado
Si está escribiendo una aplicación reutilizable (u otro fragmento de código) y desea incluir la funcionalidad de mensajería, pero no desea que sus usuarios la habiliten si no lo desean, puede pasar un argumento de palabra clave adicional fail_silently=True
a cualquiera de los add_message
familia de métodos. Por ejemplo:
messages.add_message( request, messages.SUCCESS, 'Profile details updated.', fail_silently=True, ) messages.info(request, 'Hello world.', fail_silently=True)
Nota
Configuración fail_silently=True
solo esconde el MessageFailure
que de otro modo ocurriría cuando el marco de mensajes se deshabilita y uno intenta usar uno de los add_message
familia de métodos. No oculta fallas que puedan ocurrir por otras razones.
Agregar mensajes en vistas basadas en clases
-
class views.SuccessMessageMixin
-
Agrega un atributo de mensaje de éxito a
FormView
clases basadas-
get_success_message(cleaned_data)
-
cleaned_data
son los datos limpios del formulario que se utiliza para formatear 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á disponible para la interpolación de cadenas utilizando el %(field_name)s
sintaxis. Para ModelForms, si necesita acceder a los campos del archivo guardado object
anular el get_success_message()
método.
Vistas de ejemplo.py 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, )
Caducidad de mensajes
Los mensajes se marcan para que se borren cuando se itera la instancia de almacenamiento (y se borran cuando se procesa la respuesta).
Para evitar que los mensajes se borren, puede configurar 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
Comportamiento de solicitudes paralelas
Debido a la forma en que funcionan las cookies (y, por lo tanto, las sesiones), el comportamiento de cualquier backend que hace uso de cookies o sesiones no está definido cuando el mismo cliente realiza múltiples solicitudes que configuran u obtienen 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 alfabetizado en otra ventana, antes de que la primera ventana se redireccione, el mensaje puede aparecer en la segunda ventana en lugar de la primera. ventana donde se puede esperar.
En resumen, cuando se involucran múltiples solicitudes simultáneas del mismo cliente, no se garantiza que los mensajes se entreguen en la misma ventana que los creó ni, en algunos casos, en absoluto. Tenga en cuenta que esto no suele ser un problema en la mayoría de las aplicaciones y no será un problema en HTML5, donde cada ventana / pestaña tendrá su propio contexto de navegación.
Ajustes
Unos pocos ajustes le da control sobre el comportamiento del mensaje:
MESSAGE_LEVEL
MESSAGE_STORAGE
MESSAGE_TAGS
Para los backends que usan cookies, la configuración de la cookie se toma de la configuración de la cookie de sesión:
SESSION_COOKIE_DOMAIN
SESSION_COOKIE_SECURE
SESSION_COOKIE_HTTPONLY