Plantillas Jinja en Flask: Reutilización de Código HTML
Clase 13 de 18 • Curso de Flask
Resumen
La implementación de interfaces atractivas y funcionales es un aspecto fundamental en el desarrollo web moderno. Mientras que el backend proporciona la lógica y funcionalidad, el frontend es la cara visible de nuestra aplicación y determina en gran medida la experiencia del usuario. En este contenido, exploraremos cómo mejorar la apariencia de nuestra aplicación Flask utilizando Jinja, un poderoso sistema de plantillas que nos permite organizar y reutilizar nuestro código HTML de manera eficiente.
¿Qué es Jinja y cómo mejora nuestro desarrollo frontend?
Jinja es el manejador de plantillas integrado en Flask que ofrece grandes ventajas para el desarrollo frontend. Su principal beneficio es evitar la duplicación de código HTML, permitiéndonos mantener nuestro código organizado en diferentes archivos y reutilizarlo según sea necesario.
Para trabajar con Jinja de manera más eficiente, podemos instalar la extensión "Better Jinja" en nuestro editor de código, lo que facilita la escritura y el autocompletado de código Jinja.
Creando una plantilla base con Jinja
El primer paso para implementar Jinja en nuestra aplicación es crear una plantilla base que contendrá la estructura común a todas nuestras páginas:
- Creamos un archivo llamado
base.html
en la carpeta templates - Definimos la estructura básica de HTML5
- Agregamos bloques que serán redefinidos en las plantillas hijas
<!-- Seleccionamos Jinja HTML como lenguaje -->
{% block app_notas %}{% endblock %}
<body style="background-color: aqua;">
{% block content %}{% endblock %}
</body>
Los bloques ({% block nombre %}{% endblock %}
) son áreas que pueden ser sobrescritas por las plantillas que extiendan de esta base.
Extendiendo la plantilla base
Para utilizar nuestra plantilla base en otras vistas, usamos la directiva {% extends %}
:
{% extends "base.html" %}
{% block content %}
<div>
Lorem ipsum dolor sit amet...
</div>
{% endblock %}
Es importante entender que solo el contenido dentro de los bloques definidos será visible en la página final. Todo el contenido que no esté dentro de un bloque redefinido será ignorado.
¿Cómo implementar elementos comunes en todas las páginas?
Una de las ventajas de usar plantillas base es la capacidad de definir elementos que aparecerán en todas las páginas de nuestra aplicación, como barras de navegación, pies de página o sistemas de mensajes.
Sistema de mensajes flash
Para implementar un sistema de mensajes que aparezca en todas las páginas, podemos colocar el código correspondiente en la plantilla base:
<!-- En base.html, antes del bloque content -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
De esta manera, los mensajes flash se mostrarán en cualquier página que extienda de nuestra plantilla base.
Mejorando la apariencia con Tailwind CSS
Para mejorar la apariencia de nuestra aplicación, podemos utilizar frameworks CSS como Tailwind. En nuestra plantilla base mejorada, incluimos:
- La integración de Tailwind CSS mediante un script
- Fuentes personalizadas desde Google Fonts
- Una barra de navegación (navbar)
- Un sistema de mensajes con colores según la categoría (success, error, warning)
- Un contenedor principal con márgenes y padding adecuados
- Un pie de página
<!-- Ejemplo de base.html mejorado -->
<!DOCTYPE html>
<html>
<head>
<title>{% block app_notas %}Notas App{% endblock %}</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
</head>
<body class="font-roboto">
<nav class="bg-blue-600 text-white p-4">
<h1 class="text-xl font-bold">Notas App</h1>
</nav>
<!-- Sistema de mensajes con colores según categoría -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
{% if category == 'success' %}
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 mb-4">{{ message }}</div>
{% elif category == 'error' %}
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4">{{ message }}</div>
{% elif category == 'warning' %}
<div class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 mb-4">{{ message }}</div>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
<main class="container mx-auto p-4">
{% block content %}{% endblock %}
</main>
<footer class="bg-gray-200 p-4 text-center text-gray-600">
© 2023 Notas App
</footer>
</body>
</html>
¿Cómo personalizar las vistas específicas de nuestra aplicación?
Una vez que tenemos nuestra plantilla base, podemos personalizar cada vista específica extendiendo de ella y redefiniendo los bloques necesarios.
Personalizando la vista de inicio
Para la página principal que muestra la lista de notas, extendemos de la plantilla base y personalizamos el contenido:
{% extends "base.html" %}
{% block app_notas %}Listado de Notas{% endblock %}
{% block content %}
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold">Mis Notas</h2>
<a href="{{ url_for('create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Crear Nota
</a>
</div>
{% if notes %}
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{% for note in notes %}
<div class="bg-white shadow-md rounded-lg p-4">
<h3 class="text-xl font-bold mb-2">{{ note.title }}</h3>
<p class="text-gray-700 mb-4">{{ note.content }}</p>
<p class="text-sm text-gray-500">Creada: {{ note.created_at }}</p>
<div class="flex justify-end mt-4">
<a href="{{ url_for('edit', id=note.id) }}" class="bg-yellow-500 hover:bg-yellow-700 text-white font-bold py-1 px-3 rounded mr-2">
Editar
</a>
<a href="{{ url_for('delete', id=note.id) }}" class="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-3 rounded">
Eliminar
</a>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="bg-gray-100 p-8 text-center rounded-lg">
<p class="text-xl text-gray-600">No hay notas disponibles. ¡Crea una nueva!</p>
</div>
{% endif %}
{% endblock %}
Agregando campos a nuestro modelo
Para mejorar nuestra aplicación, podemos agregar un campo de fecha de creación a nuestro modelo de Nota:
class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=db.func.now())
El parámetro default=db.func.now()
asegura que cada nueva nota tenga automáticamente la fecha y hora actual como su fecha de creación.
La implementación de Jinja en nuestra aplicación Flask nos permite crear interfaces más atractivas y mantener nuestro código organizado y reutilizable. Mediante el uso de plantillas base y bloques, podemos definir elementos comunes y personalizarlos según sea necesario en cada vista específica. Además, la integración con frameworks como Tailwind CSS nos facilita el diseño de interfaces modernas y responsivas. ¿Has implementado Jinja en tus proyectos Flask? Comparte tus experiencias y cómo has mejorado tus formularios con Tailwind en los comentarios.