Flask
Tutorial Flask: Sintaxis Jinja2
Aprende la sintaxis fundamental y estructuras de control en Jinja2 para crear plantillas dinámicas con Flask de forma eficiente y segura.
Aprende Flask y certifícateSintaxis básica Jinja2
Jinja2 es el motor de plantillas que Flask utiliza por defecto para generar contenido HTML dinámico. Su sintaxis permite combinar código Python con HTML de manera elegante, separando la lógica de presentación del controlador y facilitando el mantenimiento del código.
Delimitadores fundamentales
Jinja2 utiliza tres tipos de delimitadores principales que definen cómo se interpreta el contenido dentro de las plantillas:
{{ }}
- Para mostrar variables y expresiones{% %}
- Para estructuras de control (condicionales, bucles){# #}
- Para comentarios que no aparecen en el HTML final
<!DOCTYPE html>
<html>
<head>
<title>{{ titulo_pagina }}</title>
</head>
<body>
{# Este es un comentario que no se verá en el navegador #}
<h1>{{ mensaje_bienvenida }}</h1>
{% if usuario_logueado %}
<p>Bienvenido de vuelta</p>
{% endif %}
</body>
</html>
Mostrar variables
La interpolación de variables se realiza mediante las llaves dobles {{ }}
. Jinja2 automáticamente escapa el contenido HTML para prevenir ataques XSS, convirtiendo caracteres especiales en entidades HTML seguras:
<!-- En el controlador: nombre = "Ana García" -->
<h2>Hola {{ nombre }}</h2>
<!-- Resultado: <h2>Hola Ana García</h2> -->
<!-- En el controlador: edad = 25 -->
<p>Tienes {{ edad }} años</p>
<!-- Resultado: <p>Tienes 25 años</p> -->
Para acceder a propiedades de objetos o elementos de diccionarios, utiliza la notación de punto:
<!-- En el controlador: usuario = {"nombre": "Carlos", "email": "carlos@email.com"} -->
<p>Usuario: {{ usuario.nombre }}</p>
<p>Email: {{ usuario.email }}</p>
<!-- También funciona con listas -->
<!-- En el controlador: colores = ["rojo", "verde", "azul"] -->
<p>Primer color: {{ colores[0] }}</p>
Filtros básicos
Los filtros modifican el contenido de las variables antes de mostrarlas. Se aplican usando el símbolo pipe |
después de la variable:
<!-- Convertir a mayúsculas -->
<h3>{{ nombre | upper }}</h3>
<!-- Convertir a minúsculas -->
<p>{{ email | lower }}</p>
<!-- Capitalizar primera letra -->
<span>{{ ciudad | capitalize }}</span>
<!-- Mostrar longitud -->
<small>Tu nombre tiene {{ nombre | length }} caracteres</small>
El filtro default
es especialmente útil para manejar valores que pueden estar vacíos:
<!-- Si 'descripcion' está vacía, muestra el texto por defecto -->
<p>{{ descripcion | default("Sin descripción disponible") }}</p>
<!-- Versión abreviada -->
<p>{{ descripcion or "Sin descripción disponible" }}</p>
Expresiones y operadores
Jinja2 permite realizar operaciones matemáticas y comparaciones directamente en las plantillas:
<!-- Operaciones matemáticas -->
<p>Total: {{ precio * cantidad }}</p>
<p>Descuento: {{ precio * 0.1 }}</p>
<!-- Concatenación de strings -->
<h2>{{ nombre + " " + apellido }}</h2>
<!-- Comparaciones -->
<p>{{ edad >= 18 and "Mayor de edad" or "Menor de edad" }}</p>
Funciones integradas
Jinja2 incluye varias funciones útiles que puedes usar directamente en las plantillas:
<!-- Obtener longitud -->
<p>Hay {{ range(1, 6) | length }} elementos</p>
<!-- Generar rangos -->
{% for numero in range(1, 4) %}
<span>{{ numero }}</span>
{% endfor %}
<!-- Función url_for para generar URLs -->
<a href="{{ url_for('inicio') }}">Ir al inicio</a>
Espacios en blanco y formato
Jinja2 respeta los espacios en blanco del HTML, pero puedes controlar el formato usando guiones en los delimitadores:
<!-- Sin control de espacios -->
<ul>
{% for item in lista %}
<li>{{ item }}</li>
{% endfor %}
</ul>
<!-- Eliminando espacios extra -->
<ul>
{%- for item in lista %}
<li>{{ item }}</li>
{%- endfor %}
</ul>
Escapado de contenido
Por defecto, Jinja2 escapa automáticamente el contenido HTML para seguridad. Si necesitas mostrar HTML sin escapar, usa el filtro safe
:
<!-- Contenido escapado (seguro) -->
<p>{{ mensaje_usuario }}</p>
<!-- Contenido sin escapar (usar con precaución) -->
<div>{{ contenido_html | safe }}</div>
<!-- Alternativa usando autoescape -->
{% autoescape false %}
<div>{{ contenido_html }}</div>
{% endautoescape %}
Esta sintaxis fundamental de Jinja2 te permite crear plantillas dinámicas que reciben datos desde tus controladores Flask y los presentan de manera estructurada en el navegador. La separación clara entre la lógica de presentación y los datos facilita el mantenimiento y la reutilización del código en aplicaciones web.
Variables y estructuras de control
Las estructuras de control en Jinja2 permiten crear plantillas dinámicas que adaptan su contenido según los datos recibidos desde el controlador. Estas estructuras utilizan la sintaxis {% %}
y proporcionan la lógica necesaria para mostrar información de manera condicional o repetitiva.
Condicionales con if
La estructura if
evalúa condiciones y muestra contenido según el resultado. Es fundamental para crear interfaces que se adapten al estado de la aplicación:
{% if usuario %}
<div class="bienvenida">
<h2>Hola {{ usuario.nombre }}</h2>
<a href="{{ url_for('perfil') }}">Ver perfil</a>
</div>
{% else %}
<div class="login-prompt">
<p>Por favor, inicia sesión</p>
<a href="{{ url_for('login') }}">Acceder</a>
</div>
{% endif %}
Las condiciones múltiples se manejan con elif
, permitiendo evaluar varios escenarios:
{% if puntuacion >= 90 %}
<span class="excelente">Excelente trabajo</span>
{% elif puntuacion >= 70 %}
<span class="bueno">Buen trabajo</span>
{% elif puntuacion >= 50 %}
<span class="regular">Puede mejorar</span>
{% else %}
<span class="insuficiente">Necesita más práctica</span>
{% endif %}
Operadores lógicos en condicionales
Jinja2 soporta operadores lógicos que permiten crear condiciones más complejas:
{% if edad >= 18 and tiene_licencia %}
<p>Puede conducir</p>
{% endif %}
{% if es_admin or es_moderador %}
<button class="btn-admin">Panel de administración</button>
{% endif %}
{% if not usuario.bloqueado %}
<form method="post">
<button type="submit">Enviar comentario</button>
</form>
{% endif %}
Verificación de existencia y contenido
Es común verificar si una variable existe o tiene contenido antes de mostrarla:
{% if productos %}
<h3>Productos disponibles: {{ productos | length }}</h3>
{% else %}
<p>No hay productos disponibles</p>
{% endif %}
{% if usuario.avatar %}
<img src="{{ usuario.avatar }}" alt="Avatar">
{% else %}
<div class="avatar-placeholder">Sin imagen</div>
{% endif %}
Bucles con for
El bucle for
itera sobre listas, diccionarios y otros objetos iterables para generar contenido repetitivo:
<ul class="lista-productos">
{% for producto in productos %}
<li>
<h4>{{ producto.nombre }}</h4>
<p>Precio: {{ producto.precio }}€</p>
<span>Stock: {{ producto.stock }}</span>
</li>
{% endfor %}
</ul>
Variables especiales en bucles
Jinja2 proporciona variables especiales dentro de los bucles que ofrecen información útil sobre la iteración actual:
<table>
{% for usuario in usuarios %}
<tr class="{% if loop.index % 2 == 0 %}par{% else %}impar{% endif %}">
<td>{{ loop.index }}</td>
<td>{{ usuario.nombre }}</td>
<td>{{ usuario.email }}</td>
{% if loop.first %}
<td><strong>Primer usuario</strong></td>
{% elif loop.last %}
<td><strong>Último usuario</strong></td>
{% else %}
<td>Usuario {{ loop.index }} de {{ loop.length }}</td>
{% endif %}
</tr>
{% endfor %}
</table>
Las variables de bucle más útiles incluyen:
loop.index
- Número de iteración actual (empezando en 1)loop.index0
- Número de iteración actual (empezando en 0)loop.first
- True si es la primera iteraciónloop.last
- True si es la última iteraciónloop.length
- Total de elementos en la iteración
Bucles con diccionarios
Los diccionarios se pueden iterar de diferentes maneras según la información que necesites mostrar:
<!-- Iterar solo valores -->
{% for valor in configuracion.values() %}
<p>{{ valor }}</p>
{% endfor %}
<!-- Iterar claves y valores -->
{% for clave, valor in configuracion.items() %}
<div class="config-item">
<strong>{{ clave }}:</strong> {{ valor }}
</div>
{% endfor %}
Bucles anidados
Los bucles anidados permiten trabajar con estructuras de datos más complejas:
{% for categoria in categorias %}
<div class="categoria">
<h3>{{ categoria.nombre }}</h3>
<div class="productos">
{% for producto in categoria.productos %}
<div class="producto">
<h4>{{ producto.nombre }}</h4>
<p>{{ producto.descripcion }}</p>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
Manejo de bucles vacíos
La cláusula else
en bucles se ejecuta cuando la lista está vacía, evitando mostrar contenedores vacíos:
<div class="comentarios">
<h3>Comentarios</h3>
{% for comentario in comentarios %}
<div class="comentario">
<strong>{{ comentario.autor }}</strong>
<p>{{ comentario.texto }}</p>
</div>
{% else %}
<p class="sin-comentarios">Aún no hay comentarios</p>
{% endfor %}
</div>
Filtrado en bucles
Puedes filtrar elementos durante la iteración usando condiciones dentro del bucle:
<h3>Productos en oferta</h3>
{% for producto in productos %}
{% if producto.descuento > 0 %}
<div class="oferta">
<h4>{{ producto.nombre }}</h4>
<span class="precio-original">{{ producto.precio }}€</span>
<span class="precio-oferta">{{ producto.precio * (1 - producto.descuento) }}€</span>
</div>
{% endif %}
{% endfor %}
Asignación de variables
Jinja2 permite asignar variables dentro de las plantillas para reutilizar valores calculados:
{% set precio_total = producto.precio * cantidad %}
{% set descuento_aplicado = precio_total * 0.1 %}
<div class="resumen-compra">
<p>Subtotal: {{ precio_total }}€</p>
<p>Descuento: -{{ descuento_aplicado }}€</p>
<p><strong>Total: {{ precio_total - descuento_aplicado }}€</strong></p>
</div>
Combinando estructuras de control
Las estructuras se pueden combinar para crear lógicas más sofisticadas:
{% for pedido in pedidos %}
<div class="pedido">
<h4>Pedido #{{ pedido.id }}</h4>
{% if pedido.estado == 'pendiente' %}
<span class="estado pendiente">Pendiente de pago</span>
{% elif pedido.estado == 'procesando' %}
<span class="estado procesando">En preparación</span>
{% elif pedido.estado == 'enviado' %}
<span class="estado enviado">Enviado</span>
{% endif %}
{% if pedido.productos %}
<ul>
{% for producto in pedido.productos %}
<li>{{ producto.nombre }} x{{ producto.cantidad }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% else %}
<p>No tienes pedidos realizados</p>
{% endfor %}
Estas estructuras de control proporcionan la flexibilidad necesaria para crear interfaces dinámicas que respondan a los datos enviados desde tus controladores Flask, manteniendo la separación entre la lógica de negocio y la presentación visual.
Otras lecciones de Flask
Accede a todas las lecciones de Flask y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Flask
Introducción Y Entorno
Instalación Y Configuración Flask Con Venv
Introducción Y Entorno
Rutas Endpoints Rest Get
Api Rest
Respuestas Con Esquemas Flask Marshmallow
Api Rest
Rutas Endpoints Rest Post, Put Y Delete
Api Rest
Manejo De Errores Y Códigos De Estado Http
Api Rest
Ejercicios de programación de Flask
Evalúa tus conocimientos de esta lección Sintaxis Jinja2 con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.