Plantillas

Flask utiliza Jinja2 como motor de plantillas. Obviamente, usted es libre de utilizar un motor de plantillas diferente, pero todavía tiene que instalar Jinja2 para ejecutar Flask en sí. Este requisito es necesario para habilitar extensiones ricas. Una extensión puede depender de que Jinja2 esté presente.

Esta sección sólo da una introducción muy rápida de cómo Jinja2 está integrado en Flask. Si quieres información sobre la sintaxis del motor de plantillas, dirígete a la documentación oficial de Jinja2 Template Documentation para más información.

Configuración de Jinja

A menos que se personalice, Jinja2 es configurado por Flask como sigue:

  • autoescaping is enabled for all templates ending in .html, .htm, .xml, .xhtml, as well as .svg when using render_template().

  • se activa el autoescapado para todas las cadenas cuando se utiliza render_template_string().

  • una plantilla tiene la capacidad de optar por el autoescapado con la etiqueta {% autoescape %}.

  • Flask inserta un par de funciones globales y ayudantes en el contexto de Jinja2, además de los valores que están presentes por defecto.

Contexto estándar

Las siguientes variables globales están disponibles en las plantillas de Jinja2 por defecto:

config

El objeto de configuración actual (flask.Flask.config)

Changelog

Distinto en la versión 0.10: Ahora está siempre disponible, incluso en las plantillas importadas.

Nuevo en la versión 0.6.

request

El objeto de solicitud actual (flask.request). Esta variable no está disponible si la plantilla se renderizó sin un contexto de solicitud activo.

session

El objeto de sesión actual (flask.session). Esta variable no está disponible si la plantilla se renderizó sin un contexto de solicitud activo.

g

El objeto vinculado a la solicitud para las variables globales (flask.g). Esta variable no está disponible si la plantilla se renderizó sin un contexto de solicitud activo.

url_for()

La función flask.url_for().

get_flashed_messages()

La función flask.get_flashed_messages().

El comportamiento del contexto Jinja

Estas variables se añaden al contexto de las variables, no son variables globales. La diferencia es que por defecto no aparecerán en el contexto de las plantillas importadas. Esto se debe en parte a consideraciones de rendimiento, y en parte para mantener las cosas explícitas.

¿Qué significa esto para usted? Si tienes una macro que quieres importar, que necesita acceder al objeto de petición tienes dos posibilidades:

  1. pasas explícitamente la solicitud a la macro como parámetro, o el atributo del objeto de solicitud que te interesa.

  2. importas la macro «with context».

La importación with context tiene este aspecto:

{% from '_helpers.html' import my_macro with context %}

Controlar el autoescapado

Autoescaping es el concepto de escapar automáticamente los caracteres especiales para usted. Los caracteres especiales en el sentido de HTML (o XML, y por tanto XHTML) son &, >, <, " así como '. Dado que estos caracteres tienen un significado específico en los documentos por sí mismos, hay que sustituirlos por las llamadas «entidades» si se quiere utilizarlos para el texto. No hacerlo así no sólo causaría la frustración del usuario por la imposibilidad de utilizar estos caracteres en el texto, sino que también puede dar lugar a problemas de seguridad. (véase Secuencia de comandos en sitios cruzados (XSS))

Sin embargo, a veces necesitarás desactivar el autoescapado en las plantillas. Este puede ser el caso si quieres inyectar explícitamente HTML en las páginas, por ejemplo si vienen de un sistema que genera HTML seguro como un convertidor de markdown a HTML.

Hay tres maneras de lograrlo:

  • In the Python code, wrap the HTML string in a Markup object before passing it to the template. This is in general the recommended way.

  • Dentro de la plantilla, utilice el filtro |safe para marcar explícitamente una cadena como HTML seguro ({{ myvariable|safe }})

  • Desactivar temporalmente el sistema de autoescape por completo.

Para desactivar el sistema de autoescape en las plantillas, puede utilizar el bloque {% autoescape %}:

{% autoescape false %}
    <p>autoescaping is disabled here
    <p>{{ will_not_be_escaped }}
{% endautoescape %}

Siempre que haga esto, tenga mucho cuidado con las variables que utiliza en este bloque.

Registro de filtros

Si quieres registrar tus propios filtros en Jinja2 tienes dos formas de hacerlo. Puedes ponerlos a mano en el jinja_env de la aplicación o utilizar el decorador template_filter().

Los dos ejemplos siguientes funcionan igual y ambos invierten un objeto:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

En el caso del decorador el argumento es opcional si quieres usar el nombre de la función como nombre del filtro. Una vez registrado, puedes usar el filtro en tus plantillas de la misma manera que los filtros incorporados de Jinja2, por ejemplo si tienes una lista de Python en contexto llamada mylist:

{% for x in mylist | reverse %}
{% endfor %}

Procesadores de contexto

Para inyectar nuevas variables automáticamente en el contexto de una plantilla, existen procesadores de contexto en Flask. Los procesadores de contexto se ejecutan antes de que la plantilla sea renderizada y tienen la capacidad de inyectar nuevos valores en el contexto de la plantilla. Un procesador de contexto es una función que devuelve un diccionario. Las claves y valores de este diccionario se fusionan con el contexto de la plantilla, para todas las plantillas de la aplicación:

@app.context_processor
def inject_user():
    return dict(user=g.user)

El procesador de contexto anterior hace que una variable llamada user esté disponible en la plantilla con el valor de g.user. Este ejemplo no es muy interesante porque g está disponible en las plantillas de todos modos, pero da una idea de cómo funciona.

Las variables no se limitan a los valores; un procesador de contexto también puede hacer que las funciones estén disponibles para las plantillas (ya que Python permite pasar alrededor de las funciones):

@app.context_processor
def utility_processor():
    def format_price(amount, currency="€"):
        return f"{amount:.2f}{currency}"
    return dict(format_price=format_price)

El procesador de contexto anterior hace que la función format_price esté disponible para todas las plantillas:

{{ format_price(0.33) }}

También podría construir format_price como un filtro de plantilla (ver Registro de filtros), pero esto demuestra cómo pasar funciones en un procesador de contexto.

Streaming

Puede ser útil no renderizar toda la plantilla como una cadena completa, sino renderizarla como un flujo, produciendo cadenas incrementales más pequeñas. Esto puede ser utilizado para el flujo de HTML en trozos para acelerar la carga inicial de la página, o para ahorrar memoria cuando se renderiza una plantilla muy grande.

El motor de plantillas de Jinja2 soporta la representación de una plantilla pieza por pieza, devolviendo un iterador de cadenas. Flask proporciona las funciones stream_template() y stream_template_string() para facilitar su uso.

from flask import stream_template

@app.get("/timeline")
def timeline():
    return stream_template("timeline.html")

Estas funciones aplican automáticamente la envoltura stream_with_context() si una petición está activa, para que siga estando disponible en la plantilla.