El aviso de que algo ha ido bien, que sobrevive a una redirección, y la lista de la sesión que se niega a crecer.
⏱ 14 min de lectura
Desde la lección 24 hay un agujero apuntado y sin tapar: guardas un contacto, la aplicación redirige, y no hay ninguna señal de que haya ido bien. Ese es el precio del patrón de la lección 2, porque después de redirigir la vista original ya no existe y su contexto tampoco.
Django trae la pieza para eso, y está construida sobre la que también permite guardar cualquier cosa entre peticiones. Las dos van juntas en esta lección porque una usa la otra.
Ya estaba todo puesto desde la lección 4: la aplicación en INSTALLED_APPS, el componente en MIDDLEWARE y el procesador de contexto en TEMPLATES. Solo hay que usarlo.
contactos/views.py
from django.contrib import messages
defnuevo(peticion):if formulario.is_valid():
formulario.save()
messages.success(peticion,'Contacto guardado.')return redirect('contactos:lista')
Y en la plantilla base, para que salga en cualquier página. Ese es el bloque mensajes que la lección 18 recomendó dejar previsto:
plantillas/base.html
{% block mensajes %}{% if messages %}<ul class="mensajes">{% for m in messages %}<li class="{{ m.tags }}">{{ m }}</li>{% endfor %}</ul>{% endif %}{% endblock %}
Salida en pantalla
[25|success|success] Contacto guardado.
[30|warning|warning] Le falta el teléfono.
Dos cosas que hacen que esto funcione. La variable messages está en todas las plantillas sin que ninguna vista la pase, por el procesador de contexto de la lección 33. Y m.tags es la clase CSS del nivel, lo que permite pintar los verdes de los rojos con dos reglas.
después de la redirección -> los dos mensajes
al recargar la página -> SIN MENSAJES
Un mensaje se consume al leerlo. Es lo que se quiere: el aviso de "guardado" no debe seguir ahí al recargar.
Y tiene una consecuencia que desconcierta: si una plantilla recorre messages en un sitio y otra parte de la misma página vuelve a recorrerlo, la segunda vez está vacío. Cuando haga falta usarlos dos veces, se guardan en una variable con el {% with %} de la lección 17.
En la medición de arriba se mandaron tres mensajes y solo salieron dos: el de debug no aparece. No es un fallo, es que MESSAGE_LEVEL vale INFO, o sea 20, y lo que esté por debajo se descarta.
Eso se cambia en los ajustes, y es útil en desarrollo:
agenda/settings.py
MESSAGE_LEVEL =10# que se vean también los de depuración
Las cinco funciones son messages.debug, info, success, warning y error. Y con messages.error se puede avisar de un problema sin que sea un error del formulario, que es justo lo que faltaba en algunos casos de la lección 27.
Se usa como un diccionario normal: corchetes, get, pop, del, in. Lo que se guarda tiene que poder serializarse a JSON, así que valen textos, números, listas y diccionarios, y no valen objetos de modelo. Lo que se guarda de un objeto es su identificador.
En la cookie solo va la clave; los datos están en el servidor. Ahí se ve también cómo se guarda la sesión iniciada de la lección 32: tres entradas con el identificador del usuario, el sistema que lo autenticó y un resumen de su contraseña, que es lo que hace que cambiar la contraseña cierre las demás sesiones.
Los otros motores, por si el de serie no encaja:
SESSION_ENGINE
Cuándo
backends.db
Lo de serie. Una consulta por petición
backends.cache
Rápido; se pierde todo si se reinicia la caché
backends.cached_db
Lee de la caché y escribe en las dos. Lo habitual con tráfico
backends.signed_cookies
Sin servidor; los datos viajan en la cookie, firmados pero legibles
El último engaña: firmar no es cifrar. Cualquiera puede leer lo que hay dentro, así que no sirve para nada que no deba verse.
Y una tarea de mantenimiento que se olvida siempre:
consola
python manage.py clearsessions
Django no borra las sesiones caducadas solo. Con el motor de base de datos, esa tabla crece hasta hacerse enorme, y esa orden hay que programarla.