Django
Tutorial Django: Plantillas con Django Template Language
Django: Aprende a manejar templates para separar lógica y presentación. Implementa plantillas desde controladores para crear aplicaciones web completas con Django Template Language DTL.
Aprende Django GRATIS y certifícateCreación y uso de templates desde controladores
En Django, las plantillas permiten separar la lógica de negocio de la presentación, facilitando el desarrollo de aplicaciones web. Para aprovechar esta funcionalidad, es esencial crear los archivos de plantilla y renderizarlos desde los controladores (vistas).
Es fundamental configurar correctamente el directorio donde se almacenarán las plantillas. En el archivo settings.py
, se establece la variable TEMPLATES
, donde se especifica el directorio de plantillas:
# settings.py
import os
# ADVERTENCIA: Esta configuración ya viene predefinida y no es necesario modificarla,
# a menos que tengas pleno conocimiento de lo que estás haciendo.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
# ...
},
]
Con esta configuración, Django buscará las plantillas en la carpeta templates
situada en el directorio base del proyecto, además de en las carpetas templates
de cada aplicación instalada gracias a APP_DIRS
.
Una vez configurado el directorio, se pueden crear los archivos de plantilla con extensión .html
. Por ejemplo, se puede crear un archivo index.html
en la carpeta templates
:
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Página de Inicio</title>
</head>
<body>
<h1>Bienvenido, {{ usuario }}!</h1>
<p>{{ mensaje }}</p>
</body>
</html>
En este archivo, se utiliza el Django Template Language (DTL) para insertar variables dinámicas mediante {{ usuario }}
y {{ mensaje }}
.
Para renderizar esta plantilla desde un controlador, se emplea la función render
proporcionada por Django. Esta función recibe el objeto request
, el nombre de la plantilla y un diccionario opcional de contexto con las variables que se pasarán a la plantilla:
# views.py
from django.shortcuts import render
def pagina_inicio(request):
contexto = {
'usuario': 'Laura',
'mensaje': '¡Has iniciado sesión correctamente!'
}
return render(request, 'index.html', contexto)
En este ejemplo, el controlador pagina_inicio
renderiza la plantilla index.html
y le pasa el contexto con las variables usuario
y mensaje
.
Para que esta vista sea accesible desde el navegador, es necesario asociarla a una URL en el archivo urls.py
. Django proporciona el módulo path
dentro de django.urls
, el cual permite definir rutas y enlazarlas con vistas específicas.
from django.urls import path
from .views import pagina_inicio
urlpatterns = [
path('', pagina_inicio, name='inicio'),
]
En este fragmento de código, la función path
asocia la URL raíz (''
) con la vista pagina_inicio
. De esta manera, cuando un usuario accede a la página principal del sitio web, Django ejecuta la función pagina_inicio
, renderizando la plantilla index.html
con las variables proporcionadas en el contexto.
Los controladores también pueden interactuar con los modelos para obtener datos dinámicos y pasarlos a las plantillas. Por ejemplo, si se tiene un modelo Libro
, se pueden obtener todos los libros y enviarlos a una plantilla para mostrarlos:
# views.py
from django.shortcuts import render
from .models import Libro
def lista_libros(request):
libros = Libro.objects.all()
return render(request, 'libros.html', {'libros': libros})
En la plantilla libros.html
, se utiliza la etiqueta {% for %}
de DTL para iterar sobre la lista de libros y mostrar sus atributos:
{# templates/libros.html #}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Lista de Libros</title>
</head>
<body>
<h1>Nuestro Catálogo de Libros</h1>
<ul>
{% for libro in libros %}
<li>{{ libro.titulo }} - Autor: {{ libro.autor }}</li>
{% endfor %}
</ul>
</body>
</html>
Django utiliza cargadores de plantillas para localizar las plantillas en los directorios especificados. Gracias a 'APP_DIRS': True
en la configuración de TEMPLATES
, Django buscará automáticamente en las carpetas templates
de cada aplicación instalada, facilitando el trabajo con múltiples aplicaciones.
Además de pasar variables específicas desde los controladores, es posible definir variables de contexto global que estarán disponibles en todas las plantillas. Esto se logra mediante los context processors, que se configuran en settings.py
:
# settings.py
TEMPLATES = [
{
# ...
'OPTIONS': {
'context_processors': [
# Procesadores de contexto predeterminados
'django.template.context_processors.debug',
'django.template.context_processors.request',
# Procesador de contexto personalizado
'mi_proyecto.context_processors.datos_globales',
],
},
},
]
Y se define el procesador de contexto en un archivo Python:
# mi_proyecto/context_processors.py
def datos_globales(request):
return {
'nombre_sitio': 'Biblioteca Virtual',
'año_actual': 2025,
}
De esta manera, las variables nombre_sitio
y año_actual
estarán disponibles en todas las plantillas sin necesidad de incluirlas explícitamente en el contexto de cada controlador.
Al desarrollar aplicaciones web con Django, el uso de las plantillas y su integración desde los controladores es fundamental para crear interfaces dinámicas y personalizadas.
Sintaxis básica de DTL
El Django Template Language (DTL) es el lenguaje de plantillas nativo de Django, diseñado para facilitar la generación de contenido dinámico en las aplicaciones web. Su sintaxis es sencilla y permite integrar el contenido dinámico proporcionado por las vistas.
Variables y expresión de variables
Para insertar variables en una plantilla, se utilizan las dobles llaves {{ }}
. Dentro de estas llaves, se coloca el nombre de la variable que se desea mostrar:
<p>Hola, {{ usuario }}</p>
En este ejemplo, la variable usuario será reemplazada por el valor correspondiente en el contexto proporcionado por la vista. Si la variable no existe en el contexto, se mostrará una cadena vacía.
Es posible acceder a atributos de objetos y elementos de listas o diccionarios utilizando la notación de punto o corchetes:
<p>Tu email es: {{ usuario.email }}</p>
<p>Primer elemento: {{ lista.0 }}</p>
<p>Valor del diccionario: {{ diccionario["clave"] }}</p>
Filtros
Los filtros permiten modificar el valor de una variable antes de ser mostrada. Se aplican utilizando el carácter |
seguido del nombre del filtro:
<p>Nombre en mayúsculas: {{ usuario.nombre|upper }}</p>
<p>Fecha formateada: {{ articulo.fecha_publicacion|date:"d M Y" }}</p>
Algunos filtros comunes son:
upper
: convierte el texto a mayúsculas.lower
: convierte el texto a minúsculas.truncatechars:num
: corta el texto después de un número específico de caracteres.date:"formato"
: formatea objetos de fecha según el formato especificado.
Es posible encadenar múltiples filtros para aplicar varias transformaciones:
<p>{{ texto|lower|truncatechars:50 }}</p>
En este caso, el texto se convertirá a minúsculas y luego se truncará a 50 caracteres.
Comentarios
Para incluir comentarios en las plantillas que no serán renderizados en el HTML resultante, se emplea la siguiente sintaxis {# #}
:
{# Esto es un comentario y no se mostrará en el HTML final #}
<p>Contenido visible</p>
Los comentarios son útiles para anotar partes de la plantilla sin afectar el resultado final.
Escapado de caracteres
Por defecto, Django aplica auto-escape a las variables para prevenir ataques de inyección de código. Esto significa que caracteres especiales en HTML serán reemplazados por sus entidades correspondientes:
<p>{{ texto_usuario }}</p>
Si texto_usuario
contiene <script>alert('Hola');</script>
, el navegador mostrará los caracteres en lugar de ejecutar el script. Si se desea mostrar el contenido sin escaparlo, se puede utilizar el filtro safe
:
<p>{{ texto_usuario|safe }}</p>
Es importante usar el filtro safe
con precaución para no introducir vulnerabilidades de seguridad en la aplicación.
Etiquetas personalizadas
Las etiquetas en DTL permiten controlar el flujo y la lógica dentro de las plantillas. Aunque las estructuras de control como {% if %}
y {% for %}
se abordan en secciones posteriores, existen etiquetas básicas que son útiles conocer.
Carga de bibliotecas
Para utilizar etiquetas y filtros adicionales, es necesario cargarlos en la plantilla con {% load %}
:
{% load humanize %}
<p>Número formateado: {{ numero|intcomma }}</p>
En este ejemplo, se carga la biblioteca humanize y se utiliza el filtro intcomma
para formatear un número con comas.
Inclusión de otras plantillas
La etiqueta {% include %}
permite incorporar el contenido de otra plantilla dentro de la actual:
<div class="header">
{% include "partials/header.html" %}
</div>
Esto es útil para reutilizar fragmentos de código y mantener una estructura consistente en el sitio.
Variables especiales
Django proporciona variables especiales que pueden ser útiles en las plantillas:
{{ forloop.counter }}
: índice del bucle actual comenzando en 1.{{ forloop.first }}
: devuelve True si es la primera iteración del bucle.{{ forloop.last }}
: devuelve True si es la última iteración del bucle.
Estas variables se utilizan dentro de bucles para controlar la presentación de elementos.
Uso de operadores
En DTL, se pueden utilizar operadores básicos dentro de expresiones:
<p>Suma: {{ numero1|add:numero2 }}</p>
El filtro add
suma dos números. También existen filtros para restar, multiplicar y realizar otras operaciones matemáticas.
Manejo de valores nulos y predeterminados
Para manejar variables que pueden ser nulas o no estar definidas, se utiliza el filtro default
o default_if_none
:
<p>{{ usuario.nombre|default:"Invitado" }}</p>
Si usuario.nombre no existe, se mostrará "Invitado" como valor predeterminado.
Funciones y filtros personalizados
Es posible crear filtros personalizados para operaciones específicas. Se definen en un archivo templatetags
dentro de una aplicación:
# mi_app/templatetags/mi_filtros.py
from django import template
register = template.Library()
@register.filter
def reverso(cadena):
return cadena[::-1]
Luego, se cargan y utilizan en la plantilla:
{% load mi_filtros %}
<p>Texto invertido: {{ texto|reverso }}</p>
Esta flexibilidad permite extender las capacidades del DTL según las necesidades de la aplicación.
La sintaxis básica de DTL proporciona herramientas para integrar datos dinámicos en las plantillas de manera segura. Comprender el uso de variables, filtros y etiquetas es fundamental para desarrollar interfaces de usuario ricas y dinámicas en Django.
Sintaxis condicional e iterativa en DTL
El Django Template Language (DTL) proporciona etiquetas para controlar el flujo lógico dentro de las plantillas, permitiendo mostrar u ocultar contenido y repetir secciones según sea necesario. Las etiquetas condicionales e iterativas son herramientas esenciales para crear interfaces dinámicas y adaptativas.
Etiquetas condicionales: {% if %}
, {% elif %}
y {% else %}
La etiqueta {% if %}
evalúa una expresión y muestra el contenido dentro del bloque solo si la expresión es verdadera. La sintaxis básica es:
{% if condición %}
<!-- Contenido si la condición es verdadera -->
{% endif %}
Por ejemplo, para mostrar un mensaje si el usuario está autenticado:
{% if usuario.is_authenticated %}
<p>Bienvenido, {{ usuario.nombre }}!</p>
{% endif %}
Se pueden utilizar las etiquetas {% elif %}
y {% else %}
para manejar múltiples casos:
{% if libros.count > 1 %}
<p>Hay {{ libros.count }} libros.</p>
{% elif libros.count == 1 %}
<p>Hay un libro.</p>
{% else %}
<p>No hay libros.</p>
{% endif %}
En este ejemplo, se verifica si el carrito tiene elementos, en caso contrario se revisa la lista de deseos, y si ninguna condición se cumple, se muestra un mensaje predeterminado.
Operadores y comparaciones en condiciones
Las condiciones en {% if %}
pueden incluir operadores lógicos y de comparación:
- Igualdad:
==
- Diferencia:
!=
- Mayor que:
>
- Menor que:
<
- Mayor o igual:
>=
- Menor o igual:
<=
- Pertenencia:
in
ynot in
- Lógicos:
and
,or
,not
Ejemplo utilizando operadores:
{% if producto.stock > 0 and producto.disponible %}
<button>Agregar al carrito</button>
{% else %}
<span>Producto no disponible</span>
{% endif %}
Es importante recordar que las expresiones en DTL son más limitadas que en Python, pero permiten evaluar la mayoría de las condiciones necesarias.
Uso de variables booleanas y valores nulos
Las variables booleanas se pueden utilizar directamente en las condiciones:
{% if suscrito %}
<p>Gracias por suscribirte a nuestro boletín.</p>
{% endif %}
Si una variable es nula o no está definida, se considera como falsa en la evaluación de la condición.
Etiquetas iterativas: {% for %}
y {% empty %}
La etiqueta {% for %}
permite iterar sobre una secuencia, como listas, tuplas o querysets, mostrando el contenido repetidamente para cada elemento. La sintaxis básica es:
{% for elemento in secuencia %}
<!-- Contenido a repetir por cada elemento -->
{% endfor %}
Por ejemplo, para listar los productos en una categoría:
<ul>
{% for producto in categoria.productos %}
<li>{{ producto.nombre }} - Precio: {{ producto.precio|floatformat:2 }}€</li>
{% endfor %}
</ul>
Variables especiales dentro del bucle
Dentro del bucle {% for %}
, se dispone de variables especiales que proporcionan información adicional:
{{ forloop.counter }}
: Número de la iteración actual, comenzando en 1.{{ forloop.counter0 }}
: Número de la iteración actual, comenzando en 0.{{ forloop.revcounter }}
: Número de iteraciones restantes, comenzando desde el total.{{ forloop.first }}
: True si es la primera iteración.{{ forloop.last }}
: True si es la última iteración.{{ forloop.parentloop }}
: Referencia al bucle padre en bucles anidados.
Ejemplo utilizando forloop.counter
:
<table>
<tr>
<th>Nº</th>
<th>Titulo</th>
<th>Autor</th>
</tr>
{% for libro in libros %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ libro.titulo }}</td>
<td>{{ libro.autor }}</td>
</tr>
{% endfor %}
</table>
Manejo de listas vacías con {% empty %}
La etiqueta {% empty %}
se utiliza para manejar casos donde la secuencia está vacía. Se coloca dentro del bloque {% for %}
y se ejecuta si la secuencia no contiene elementos:
<ul>
{% for libro in libros %}
<li>{{ libro.titulo }}</li>
{% empty %}
<li>No tienes libros.</li>
{% endfor %}
</ul>
En este ejemplo, si mensajes está vacío, se mostrará el mensaje alternativo.
Bucles anidados
Es posible anidar bucles {% for %}
para iterar sobre estructuras más complejas:
{% for autor in autores %}
<h3>Autor: {{ autor.nombre }}</h3>
<ul>
{% for libro in autor.libros.all %}
<li>
<h4>{{ libro.titulo }}</h4>
<p>{{ libro.descripcion }}</p>
</li>
{% endfor %}
</ul>
{% endfor %}
En bucles anidados, forloop.parentloop
permite acceder a la información del bucle padre si es necesario.
Buenas prácticas en el uso de etiquetas
- Mantener la lógica en las vistas: Evitar realizar cálculos complejos o lógica de negocio en las plantillas.
- Simplificar condiciones: Si las condiciones se vuelven complicadas, considerar preprocesar los datos en la vista y pasar valores más directos al contexto.
- Comentarios claros: Utilizar comentarios
{# #}
para documentar secciones de la plantilla cuando sea necesario. - Reutilización: Aprovechar la herencia de plantillas y componentes reutilizables para evitar duplicación de código.
Es importante tener en cuenta que en DTL no se pueden realizar asignaciones o llamadas a funciones arbitrarias. Esto garantiza que la lógica de negocio se mantenga en las vistas y modelos, preservando el principio de separación de responsabilidades.
Además, para mantener la seguridad, DTL restringe el acceso a ciertos métodos y atributos. Solo se pueden utilizar aquellos que son seguros y no representan un riesgo.
Herencia en plantillas DTL
La herencia de plantillas en el Django Template Language (DTL) es una técnica que permite reutilizar y organizar el código de las plantillas. Mediante la herencia, es posible definir una plantilla base que sirve como estructura común para otras plantillas, facilitando la coherencia y el mantenimiento del sitio web.
La plantilla base establece el esqueleto del documento HTML y define bloques que pueden ser sobrescritos por las plantillas hijas. Para crear una plantilla base, se utiliza la siguiente sintaxis:
{# templates/base.html #}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>
{% block titulo %}
Mi Sitio
{% endblock %}
</title>
</head>
<body>
<header>
{% block cabecera %}
<!-- Contenido de la cabecera -->
{% endblock %}
</header>
<nav>
{% block navegacion %}
<!-- Menú de navegación -->
{% endblock %}
</nav>
<main>
{% block contenido %}
<!-- Contenido principal -->
{% endblock %}
</main>
<footer>
{% block pie %}
<!-- Pie de página -->
{% endblock %}
</footer>
{% block scripts %}
<script src="{% static 'js/principal.js' %}"></script>
{% endblock %}
</body>
</html>
En este ejemplo, la plantilla base define varios bloques como titulo
, cabecera
, navegacion
, contenido
, pie
y scripts
. Las plantillas hijas pueden extender esta plantilla base y personalizar cada uno de estos bloques según sea necesario.
Para que una plantilla hija extienda la plantilla base, se utiliza la etiqueta {% extends %}
al inicio del archivo:
{% extends 'base.html' %}
{% block titulo %}Página de Inicio{% endblock %}
{% block contenido %}
<h1>Bienvenido a Nuestro Sitio Web</h1>
<p>Este es el contenido específico de la página de inicio.</p>
{% endblock %}
Es fundamental que la etiqueta {% extends %}
sea la primera línea de la plantilla hija, sin espacios ni líneas en blanco antes, para asegurar un correcto funcionamiento.
Uso de bloques y sobrescritura
Los bloques ({% block nombre_plantilla %}
) son regiones de la plantilla que pueden ser reemplazadas por las plantillas hijas. Si una plantilla hija no sobrescribe un bloque, se utilizará el contenido definido en la plantilla base. Esto permite controlar qué partes del diseño son comunes y cuáles son específicas de cada página.
Por ejemplo, si se desea modificar el menú de navegación únicamente en una página, se puede sobrescribir el bloque navegacion
en esa plantilla hija:
{% extends 'base.html' %}
{% block titulo %}Productos{% endblock %}
{% block navegacion %}
<nav>
<ul>
<li><a href="{% url 'inicio' %}">Inicio</a></li>
<li><a href="{% url 'productos' %}">Productos</a></li>
<li><a href="{% url 'contacto' %}">Contacto</a></li>
<li><a href="{% url 'ofertas' %}">Ofertas Especiales</a></li>
</ul>
</nav>
{% endblock %}
{% block contenido %}
<h2>Nuestros Productos</h2>
<!-- Listado de productos -->
{% endblock %}
Inclusión de contenido adicional
En ocasiones, es necesario añadir contenido a un bloque existente sin reemplazarlo por completo. Para ello, se utiliza la variable {{ block.super }}
, que hace referencia al contenido original del bloque en la plantilla base. Esto es útil para extender funcionalidades manteniendo la coherencia.
Por ejemplo, para agregar estilos adicionales:
{% block estilos %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'css/productos.css' %}">
{% endblock %}
Y para añadir scripts específicos:
{% block scripts %}
{{ block.super }}
<script src="{% static 'js/productos.js' %}"></script>
{% endblock %}
Herencia múltiple y jerárquica
Las plantillas en Django pueden heredar de otras que, a su vez, heredan de una plantilla base, creando una jerarquía de herencia. Por ejemplo:
base.html
: plantilla base con la estructura general.seccion.html
: hereda debase.html
y define bloques adicionales para secciones específicas.detalle.html
: hereda deseccion.html
y proporciona contenido detallado.
Esto permite crear diseños más complejos y modularizados. La plantilla seccion.html
podría ser:
{% extends 'base.html' %}
{% block contenido %}
<div class="seccion">
{% block seccion_contenido %}
<!-- Contenido de la sección -->
{% endblock %}
</div>
{% endblock %}
Y la plantilla detalle.html
:
{% extends 'seccion.html' %}
{% block seccion_contenido %}
<h2>Detalle del Producto</h2>
<p>Información detallada del producto seleccionado.</p>
{% endblock %}
Reutilización con la etiqueta include
Además de la herencia, para reutilizar fragmentos de código más pequeños o componentes comunes, se puede utilizar la etiqueta {% include %}
. Esto es especialmente útil para elementos como formularios, tarjetas de presentación o mensajes de error.
Por ejemplo, para incluir un formulario de búsqueda en varias páginas:
{% include 'partials/formulario_busqueda.html' %}
El archivo formulario_busqueda.html
contendría el código del formulario y estaría ubicado en un directorio de partials o fragmentos.
Buenas prácticas en la herencia de plantillas
Al trabajar con herencia de plantillas en Django, es recomendable seguir ciertas buenas prácticas:
- Mantener una estructura organizada: Ubicar las plantillas en directorios que reflejen su función y lugar en la jerarquía.
- Nombrar bloques claramente: Utilizar nombres descriptivos para los bloques, facilitando su comprensión y mantenimiento.
- Evitar la sobreescritura innecesaria: Sobrescribir solo los bloques que requieren cambios, respetando la estructura de la plantilla base.
- Utilizar comentarios: Añadir comentarios en las plantillas para indicar el propósito de cada bloque o sección.
- Minimizar la lógica en plantillas: Mantener la lógica de negocio en las vistas y usar las plantillas solo para la presentación.
La herencia en plantillas DTL es una herramienta esencial que mejora la modularidad, reutilización y mantenibilidad del código en proyectos Django. Al definir estructuras comunes y permitir la personalización a través de bloques, se logra un código más limpio y un desarrollo más ágil.
Todas las lecciones de Django
Accede a todas las lecciones de Django y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Django
Introducción Y Entorno
Instalación Y Configuración Django Con Venv
Introducción Y Entorno
Arquitectura De Un Proyecto Django
Introducción Y Entorno
Base De Datos Mysql En Django
Modelos Y Base De Datos
Creación De Modelos
Modelos Y Base De Datos
Asociaciones De Modelos
Modelos Y Base De Datos
Migraciones
Modelos Y Base De Datos
Operaciones Crud Y Consultas
Modelos Y Base De Datos
Enrutamiento Básico
Vistas Y Plantillas
Plantillas Con Django Template Language
Vistas Y Plantillas
Vistas Basadas En Funciones
Vistas Y Plantillas
Vistas Basadas En Clases
Vistas Y Plantillas
Middlewares
Vistas Y Plantillas
Form Vs Modelform
Formularios
Procesamiento De Formularios
Formularios
Subida De Archivos
Formularios
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el propósito y la configuración de plantillas en Django.
- Configurar correctamente el directorio de plantillas en "settings.py".
- Crear y renderizar plantillas HTML desde controladores.
- Emplear el Django Template Language (DTL) para aumentar la dinamización de contenido.
- Utilizar etiquetas de control condicional e iterativa en DTL.
- Organizar las plantillas dentro de aplicaciones Django.