Plantillas#

Las plantillas nos permiten diseñar el aspecto visual de nuestro proyecto. Podemos incorporar información dinámica, lo que las hace muy versátiles.

Una plantilla en Django está habitualmente escrita en lenguaje «html» e incorpora fragmentos de código específicos del lenguaje de plantillas de Django.

Dónde viven las plantillas#

Una plantilla es un archivo, habitualmente con extensión .html y que reside en alguna carpeta de nuestro proyecto.

Las plantillas vinculadas con una aplicación app deberían [1] residir en la subcarpeta templates/app/ de dicha aplicación. Ejemplo:

App

Ruta de plantillas

tracks

tracks/templates/tracks/

Esto, a priori, puede parecer repetitivo. Pero la razón de hacerlo así se debe a que Django busca las plantillas en todas las carpetas templates de las aplicaciones dadas de alta en el proyecto.

Por lo tanto, siguiendo este esquema podemos crear un cierto «namespace» o espacio de nombres para las plantillas de cada aplicación.

../../_images/load-template.svg

Carga de plantillas en Django#

Creando plantillas#

A continuación vamos a empezar a crear plantillas para poder mostrar información de nuestra aplicación.

Plantilla de lista#

Supongamos una primera plantilla que se encarga de mostrar todas las canciones almacenadas en la base de datos de musicalia.

tracks/templates/tracks/track/list.html#
1<ul>
2  {% for track in tracks %}
3    <li>{{ track }}</li>
4  {% endfor %}
5</ul>

Analicemos cada línea por separado:

  • L1 → Usaremos una etiqueta html <ul> para construir una lista.

  • L2 → Usamos un bucle para recorrer las canciones. Esta construcción en Django recibe el nombre de template tag (etiqueta de plantilla).

  • L3 → Usamos una etiqueta <li> y añadimos la canción en concreto que nos viene del bucle.

  • L4 → Cerramos la etiqueta de plantilla del bucle.

  • L5 → Cerramos la etiqueta html de lista.

Conceptos que se deben manejar:

Contexto:

Es el conjunto de variables al que una plantilla tiene acceso. En el ejemplo anterior la variable tracks está en el contexto ya que se ha pasado de forma explícita desde la vista.

Etiqueta de plantilla:

Las etiquetas de plantilla se escriben usando los delimitadores {% %}. Existe una amplia variedad de etiquetas de plantilla predefinidas en Django. [2]

Acceso a variable:

Para acceder a una variable en una plantilla usamos los delimitadores {{ }}.

Si ahora accedemos a http://localhost:8000/track/ veremos la lista de canciones disponibles:

../../_images/track-list.png

Plantilla de lista de canciones#

Plantilla de detalle#

Es muy habitual implementar una plantilla para ver los detalles de un objeto en concreto. En nuestro ejemplo vamos a implementar una plantilla para mostrar la información de una canción (objeto de tipo Track).

tracks/templates/tracks/track/detail.html#
 1<table>
 2  <tr>
 3    <th>Nombre</th>
 4    <td>{{ track.name }}</td>
 5  </tr>
 6  <tr>
 7    <th>Cantante</th>
 8    <td>{{ track.singer }}</td>
 9  </tr>
10  <tr>
11    <th>Duración</th>
12    <td>{{ track.length }} minutos</td>
13  </tr>
14</table>

Se puede ver que en las líneas L4, L8 y L12 estamos accediendo a los atributos de modelo del objeto track que se ha pasado al contexto de la plantilla desde la vista correspondiente.

Si ahora accedemos a http://localhost:8000/track/1/ veremos el detalle de la canción con pk=1:

../../_images/track-detail.png

Plantilla de detalle de canción#

Enlazando plantillas#

Sería muy útil poder enlazar cada una de las canciones en el listado inicial con su correspondiente detalle. Para ello vamos a modificar la plantilla de lista añadiendo el vínculo correspondiente.

Una primera aproximación sería la siguiente:

tracks/templates/tracks/track/list.html#
1<ul>
2  {% for track in tracks %}
3    <li><a href="/tracks/{{track.pk}}/">{{ track }}</a></li>  <!-- DON'T DO THIS! -->
4  {% endfor %}
5</ul>

En la L3 hemos añadido una etiqueta <a> apuntando a la url de detalle de cada canción. Pero esto se considera una mala práctica ya que, en el caso de que la url se modifique en el fichero urls.py tendríamos que rastrear todo nuestro código en busca de esa url y modificarla.

Es por ello que se recomienda usar la etiqueta de plantilla url que permite «inyectar» una url en una plantilla a partir del nombre de la url definido en el fichero urls.py. Veamos cómo quedaría nuestro ejemplo:

tracks/templates/tracks/track/list.html#
1<ul>
2  {% for track in tracks %}
3    <li><a href="{% url 'tracks:track_detail' track.pk %}">{{ track }}</a></li>
4  {% endfor %}
5</ul>

La etiqueta de plantilla {% url %} recibe:

  • El nombre de la url cualificado con su espacio de nombres. En este caso el espacio de nombres es tracks ya que se ha definido así en el atributo app_name del fichero tracks/urls.py.

  • Los argumentos necesarios. En este caso pasamos el identificador de la canción.

Por tanto, al acceder ahora a http://localhost:8000/tracks/ veríamos los enlaces correctamente:

../../_images/track-list-with-links.png

Plantilla de lista de canciones con enlaces#

Herencia de plantillas#

Supongamos que queremos poner algún tipo de cabecera a las plantillas indicando el nombre del proyecto «Musicalia». Si no tuviéramos otra herramienta, tendríamos que incluir esa cabecera en todas las plantillas que hayamos escrito.

Sin embargo, Django proporciona una característica muy útil denominada herencia de plantillas que nos permite heredar desde una plantilla base.

Plantilla base#

En una primera aproximación vamos a crear la siguiente plantilla base:

tracks/templates/tracks/base.html#
 1<html>
 2<head>
 3  <title>Musicalia</title>
 4</head>
 5<body>
 6  <h1>♫ Canciones</h1>
 7  <h2>{% block subtitle %}{% endblock %}</h2>
 8  {% block contents %}{% endblock %}
 9</body>
10</html>

Analicemos las líneas más importantes:

  • L6 → Este encabezado será común a toda la aplicación tracks.

  • L7 → Se define un bloque «vacío» subtitle con la idea de que sea completado en plantillas derivadas.

  • L8 → Se define un bloque «vacío» contents con la idea de que sea completado en plantillas derivadas.

Extendiendo plantillas#

Ahora podemos modificar las plantillas previas para extender (heredar) desde esta plantilla base. Veamos los cambios aplicados.

Empezamos con las modificaciones hechas a la plantilla de lista:

tracks/templates/tracks/track/list.html#
 1{% extends "tracks/base.html" %}
 2
 3{% block subtitle %}Lista{% endblock %}
 4
 5{% block contents %}
 6<ul>
 7  {% for track in tracks %}
 8    <li><a href="{% url 'tracks:track_detail' track.pk %}">{{ track }}</a></li>
 9  {% endfor %}
10</ul>
11{% endblock %}

Analicemos las líneas más importantes:

  • L1 → Estamos usando la etiqueta de plantilla extends para indicar que heredamos (o extendemos) la plantilla tracks/base.html. [2]

  • L3 → Estamos sobreescribiendo o «rellenando» el bloque subtitle con el contenido propio de esta plantilla.

  • L5 → Estamos sobreescribiendo o «rellenando» el bloque contents con el contenido propio de esta plantilla.

Truco

El contenido del bloque se puede rellenar en la misma línea o en varias líneas. Es más una cuestión estética de organización del código.

Podemos ver los cambios aplicados accediendo a http://localhost:8000/tracks/:

../../_images/track-list-with-inheritance.png

Plantilla de lista de canciones con herencia#

Del mismo modo, vamos a modificar la plantilla de detalle para heredar desde la plantilla base:

tracks/templates/tracks/track/detail.html#
 1{% extends "tracks/base.html" %}
 2
 3{% block subtitle %}{{ track.name }}{% endblock %}
 4
 5{% block contents %}
 6<table>
 7  <tr>
 8    <th>Nombre</th>
 9    <td>{{ track.name }}</td>
10  </tr>
11  <tr>
12    <th>Cantante</th>
13    <td>{{ track.singer }}</td>
14  </tr>
15  <tr>
16    <th>Duración</th>
17    <td>{{ track.length }} minutos</td>
18  </tr>
19</table>
20{% endblock %}

Analicemos las líneas más importantes:

  • L1 → Estamos usando la etiqueta de plantilla extends para indicar que heredamos (o extendemos) la plantilla tracks/base.html. [2]

  • L3 → Estamos sobreescribiendo o «rellenando» el bloque subtitle con el contenido propio de esta plantilla. Nótese que podemos usar objetos del contexto dentro del bloque.

  • L5 → Estamos sobreescribiendo o «rellenando» el bloque contents con el contenido propio de esta plantilla.

Podemos ver los cambios aplicados accediendo a http://localhost:8000/tracks/2/:

../../_images/track-detail-with-inheritance.png

Plantilla de detalle de canción con herencia#