Plantillas

Al ser un framework web, Django necesita una forma conveniente de generar HTML dinámicamente. El enfoque más común se basa en plantillas. Una plantilla contiene las partes estáticas de la salida HTML deseada, así como alguna sintaxis especial que describe cómo se insertará el contenido dinámico. Para ver un ejemplo práctico de cómo crear páginas HTML con plantillas, vea :doc:`Tutorial 3`</intro/tutorial03>.

Un proyecto Django se puede configurar con uno o varios motores de plantillas (o incluso ninguno si no usa plantillas). Django incluye backends integrados para su propio sistema de plantillas, creativamente denominado lenguaje de plantillas de Django (DTL), y para la popular alternativa Jinja2. Los backends para otros lenguajes de plantillas pueden estar disponibles através de terceros. También puede escribir su propio backend personalizado, consulte Custom template backend

Django define una API estándar para cargar y renderizar plantillas independientemente del backend. La carga consiste en encontrar la plantilla para un identificador determinado y preprocesarla, generalmente compilándola en una representación en memoria. Representar significa interpolar la plantilla con datos de contexto y devolver el texto resultante.

Django template language es el propio sistema de plantillas de Django. Hasta Django 1.8 era la única opción integrada disponible. Es una buena biblioteca de plantillas a pesar de que es bastante obstinada y tiene algunas idiosincrasias. Si no tiene una razón apremiante para elegir otro backend, debe usar DTL, especialmente si está escribiendo una aplicación conectable y tiene la intención de distribuir plantillas. Las aplicaciones de contribución de Django que incluyen plantillas, como django.contrib.admin, que también usa el DTL.

Por razones históricas, tanto el soporte genérico para motores de plantillas como la implementación del lenguaje de plantillas Django viven en el espacio de nombres django.template.

Advertencia

El sistema de plantillas no es seguro frente a autores de plantillas que no son de confianza. Por ejemplo, un sitio no debe permitir que sus usuarios proporcionen sus propias plantillas, ya que los autores de plantillas pueden hacer cosas como realizar ataques XSS y acceder a las propiedades de las variables de plantilla que pueden contener información confidencial.

Lenguaje de plantillas de Django

Sintaxis

Acerca de esta sección

Esta es una descripción general de la sintaxis del lenguaje de plantilla de Django. Para obtener más información, consulte la referencia de sintaxis del idioma.

Una plantilla de Django es un documento de texto o un texto de Python marcado con el lenguaje de plantillas de Django. Algunas construcciones son reconocidas e interpretadas por el motor de plantillas. Los principales son las variables y las etiquetas.

Una plantilla se representa con un contexto. La representación reemplaza las variables con sus valores, que se buscan en el contexto, y ejecuta las etiquetas. Todo lo demás se muestra tal cual.

La sintaxis del lenguaje de plantilla Django implica cuatro construcciones.

Variables

Una variable genera un valor del contexto, que es un objeto similar a un diccionario que asigna llaves a valores.

Variables are surrounded by {{ and }} like this:

My first name is {{ first_name }}. My last name is {{ last_name }}.

With a context of {'first_name': 'John', 'last_name': 'Doe'}, this template renders to:

My first name is John. My last name is Doe.

Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation:

{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}

Si una variable se resuelve como invocable, el sistema de plantillas la llamará sin argumentos y usará su resultado en lugar del invocable.

Etiquetas

Las etiquetas proporcionan una lógica arbitraria en el proceso de representación.

Esta definición es deliberadamente vaga. Por ejemplo, una etiqueta puede generar contenido, servir como estructura de control. Por ejemplo: Una declaración «if» o un bucle «for», o obtener contenido de una base de datos o incluso habilitar el acceso a otras etiquetas de plantilla.

Tags are surrounded by {% and %} like this:

{% csrf_token %}

Most tags accept arguments:

{% cycle 'odd' 'even' %}

Some tags require beginning and ending tags:

{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

Puede consultar la referencia de etiquetas integradas así como las instrucciones para escribir etiquetas personalizadas.

Filtros

Los filtros transforman los valores de las variables y los argumentos de las etiquetas.

They look like this:

{{ django|title }}

With a context of {'django': 'the web framework for perfectionists with deadlines'}, this template renders to:

The Web Framework For Perfectionists With Deadlines

Some filters take an argument:

{{ my_date|date:"Y-m-d" }}

Puede consultar la referencia de filtros integrados así como las instrucciones para escribir filtros personalizados.

Comentarios

Comments look like this:

{# this won't be rendered #}

Una etiqueta {% comment %} proporciona comentarios de varias líneas.

Componentes

Acerca de esta sección

Esta es una descripción general de la API del lenguaje de plantilla de Django. Para obtener más información, consulte la referencia de la API

Motor

django.template.Engine encapsula una instancia del sistema de plantillas de Django. La razón principal para instanciar una Engine directamente es usar el lenguaje de plantillas Django fuera de un proyecto Django.

django.template.backends.django.DjangoTemplates es un contenedor sencillo que adapta django.template.Engine a la API backend de plantilla de Django.

Plantilla

django.template.Template representa una plantilla compilada. Las plantillas se obtienen con Engine.get_template() o Engine.from_string().

Del mismo modo, django.template.backends.django.Template es un contenedor sencillo que adapta django.template.Template a la API de plantilla común.

Contexto

django.template.Context contiene algunos metadatos además de los datos de contexto. Se pasa a Template.render() para renderizar una plantilla.

django.template.RequestContext es una subclase de Context que almacena la HttpRequest actual y ejecuta procesadores de contexto de plantilla.

La API común no tiene un concepto equivalente. Los datos de contexto se pasan en un simple dict y el HttpRequest actual se pasa por separado si es necesario.

Cargadores

Los cargadores de plantillas son responsables de ubicar plantillas, cargarlas y devolver objetos Template.

Django proporciona varios cargadores de plantillas integrados y admite cargadores de plantillas personalizados.

Procesadores de contexto

Los procesadores de contexto son funciones que reciben la HttpRequest actual como argumento y devuelven un dict de datos para agregar al contexto de la renderización.

Su uso principal es agregar datos comunes compartidos por todas las plantillas al contexto sin repetir el código en cada vista.

Django proporciona muchos procesadores de contexto integrados, y también puede implementar sus propios procesadores de contexto adicionales.

Soporte para motores de plantillas

Configuración

Los motores de plantillas están configurados con la configuración TEMPLATES. Es una lista de configuraciones, una para cada motor. El valor predeterminado está vacío. El settings.py generado por el comando startproject define un valor más útil:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            # ... some options here ...
        },
    },
]

BACKEND es una ruta punteada de Python a una clase de motor de plantilla que implementa la API backend de plantilla de Django. Los backends integrados son django.template.backends.django.DjangoTemplates y django.template.backends.jinja2.Jinja2.

Dado que la mayoría de los motores cargan plantillas desde archivos, la configuración de nivel superior para cada motor contiene dos configuraciones comunes:

  • DIRS define una lista de directorios donde el motor debe buscar archivos fuente de plantilla, en orden de búsqueda.
  • APP_DIRS indica si el motor debe buscar plantillas dentro de las aplicaciones instaladas. Cada backend define un nombre convencional para el subdirectorio dentro de las aplicaciones donde se deben almacenar sus plantillas.

Si bien es poco común, es posible configurar varias instancias del mismo backend con diferentes opciones. En ese caso, debe definir un NAME para cada motor.

:settings:`OPTIONS <TEMPLATES-OPTIONS>` contiene configuraciones específicas de back-end.

Usage

El módulo django.template.loader define dos funciones para cargar plantillas.

get_template(template_name, using=None)

Esta función carga la plantilla con el nombre dado y devuelve un objeto Template.

El tipo exacto del valor devuelto depende del backend que cargó la plantilla. Cada backend tiene su propia clase Template.

get_template() prueba cada motor de plantilla en orden hasta que uno tenga éxito. Si no se puede encontrar la plantilla, genera TemplateDoesNotExist. Si se encuentra la plantilla pero contiene una sintaxis no válida, genera un TemplateSyntaxError.

La forma en que se buscan y cargan las plantillas depende del backend y la configuración de cada motor.

Si desea restringir la búsqueda a un motor de plantilla en particular, pase el NAME del motor en el argumento using.

select_template(template_name_list, using=None)

select_template() es como get_template(), excepto que toma una lista de nombres de plantillas. Prueba cada nombre en orden y devuelve la primera plantilla que existe.

Si falla la carga de una plantilla, se pueden generar las siguientes dos excepciones, definidas en django.template:

exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)

Esta excepción se genera cuando no se puede encontrar una plantilla. Acepta los siguientes argumentos opcionales para completar la template postmortem en la página de depuración:

backend
La instancia de back-end de la plantilla desde la que se originó la excepción.
tried
Una lista de las fuentes que se probaron al encontrar la plantilla. Esto tiene el formato de una lista de tuplas que contienen (origen, estado), donde origen es un objeto `similar al origen` y estado es una cadena con el motivo por el cual la plantilla no fue encontrada.
chain
Una lista de excepciones intermedias TemplateDoesNotExist generadas al intentar cargar una plantilla. Esto lo utilizan funciones, como get_template(), que intentan cargar una plantilla determinada desde varios motores.
exception TemplateSyntaxError(msg)

Esta excepción se genera cuando se encuentra una plantilla pero contiene errores.

Los objetos Template devueltos por get_template() y select_template() deben proporcionar un método render() con la siguiente firma:

Template.render(context=None, request=None)

Representa esta plantilla con un contexto dado.

Si se proporciona context, debe ser un dict. Si no se proporciona, el motor representará la plantilla con un contexto vacío.

Si se proporciona request, debe ser una HttpRequest. Luego, el motor debe hacerlo, así como el token CSRF, disponible en la plantilla. Cómo se logra esto depende de cada backend.

Aquí hay un ejemplo del algoritmo de búsqueda. Para este ejemplo, la configuración TEMPLATES es:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [
            "/home/html/example.com",
            "/home/html/default",
        ],
    },
    {
        "BACKEND": "django.template.backends.jinja2.Jinja2",
        "DIRS": [
            "/home/html/jinja2",
        ],
    },
]

Si llama a get_template('story_detail.html'), aquí están los archivos que buscará Django, en orden:

  • /home/html/example.com/story_detail.html (motor ``”django””)
  • /home/html/default/story_detail.html (motor 'django')
  • /home/html/jinja2/story_detail.html (motor 'jinja2')

Si llama a select_template(['story_253_detail.html', 'story_detail.html']), esto es lo que buscará Django:

  • /home/html/example.com/story_253_detail.html (motor 'django')
  • /home/html/default/story_253_detail.html (motor 'django')
  • /home/html/jinja2/story_253_detail.html (motor 'jinja2')
  • /home/html/example.com/story_detail.html (motor ``”django””)
  • /home/html/default/story_detail.html (motor 'django')
  • /home/html/jinja2/story_detail.html (motor 'jinja2')

Cuando Django encuentra una plantilla que existe, deja de buscar.

Use django.template.loader.select_template() for more flexibility

Puede usar select_template() para cargar plantillas de forma flexible. Por ejemplo, si ha escrito una noticia y quiere que algunas historias tengan plantillas personalizadas, use algo como select_template(['story_%s_detail.html' % story.id, 'story_detail.html']). Eso le permitirá usar una plantilla personalizada para una historia individual, con una plantilla alternativa para las historias que no tienen plantillas personalizadas.

Es posible, y preferible, organizar las plantillas en subdirectorios dentro de cada directorio que contiene plantillas. La convención es crear un subdirectorio para cada aplicación de Django, con subdirectorios dentro de esos subdirectorios según sea necesario.

Haga esto por su propia tranquilidad. Almacenar todas las plantillas en el nivel raíz de un solo directorio se puede complicar.

Para cargar una plantilla que está dentro de un subdirectorio, use una barra diagonal, así:

get_template("news/story_detail.html")

Usando la misma opción TEMPLATES que la anterior, esto intentará cargar las siguientes plantillas:

  • /home/html/example.com/news/story_detail.html (motor 'django')
  • /home/html/default/news/story_detail.html (motor 'django')
  • /home/html/jinja2/news/story_detail.html (motor 'jinja2')

Además, para reducir la naturaleza repetitiva de cargar y renderizar plantillas, Django proporciona una función de acceso directo que automatiza el proceso.

render_to_string(template_name, context=None, request=None, using=None)

render_to_string() carga una plantilla como get_template() y llama a su método render() inmediatamente. Toma los siguientes argumentos.

template_name
El nombre de la plantilla para cargar y renderizar. Si es una lista de nombres de plantillas, Django usa select_template() en lugar de get_template() para encontrar la plantilla.
context
Un dict que se utilizará como contexto de la plantilla para la representación.
request
Una HttpRequest opcional que estará disponible durante el proceso de renderización de la plantilla.
using
Un motor de plantillas opcional NAME. La búsqueda de la plantilla estará restringida a ese motor.

Ejemplo de uso:

from django.template.loader import render_to_string

rendered = render_to_string("my_template.html", {"foo": "bar"})

Consulte también el acceso directo render() que llama a render_to_string() y envía el resultado a una HttpResponse adecuada para retornarlo desde una vista.

Finalmente, puede usar los motores configurados directamente:

engines

Los motores de plantillas están disponibles en django.template.engines:

from django.template import engines

django_engine = engines["django"]
template = django_engine.from_string("Hello {{ name }}!")

La clave de búsqueda, — 'django' en este ejemplo, es el NAME del motor.

Backends incorporados

class DjangoTemplates

Establezca el BACKEND en 'django.template.backends.django.DjangoTemplates' para configurar un motor de plantillas de Django.

Cuando APP_DIRS es True, los motores DjangoTemplates buscan plantillas en el subdirectorio templates de las aplicaciones instaladas. Este nombre genérico se mantuvo por compatibilidad con versiones anteriores.

Los motores DjangoTemplates aceptan las siguientes OPTIONS:

  • 'autoescape': un valor booleano que controla si el escape automático de HTML está habilitado.

    Por defecto es True.

    Advertencia

    ¡Ajústelo a False solo si está representando plantillas que no son HTML!

  • 'context_processors': una lista de rutas punteadas de Python a invocables que se usan para llenar el contexto cuando una plantilla se procesa con una solicitud. Estos invocables toman un objeto de solicitud como argumento y devuelven un dict de elementos que se fusionarán en el contexto.

    Por defecto es una lista vacía.

    Consulte RequestContext para obtener más información.

  • 'debug': un valor booleano que activa/desactiva el modo de depuración de plantillas. Si es True, la elegante página de error mostrará un informe detallado de cualquier excepción que surja durante la representación de la plantilla. Este informe contiene el fragmento relevante de la plantilla con la línea correspondiente resaltada.

    El valor predeterminado es el de la configuración DEBUG.

  • 'loaders': una lista de rutas punteadas de Python a clases de cargadores de plantillas. Cada clase Loader sabe cómo importar plantillas desde una fuente en particular. Opcionalmente, se puede usar una tupla en lugar de una cadena. El primer elemento de la tupla debe ser el nombre de la clase Loader, y los elementos subsiguientes se pasan al Loader durante la inicialización.

    El valor predeterminado depende de los valores de DIRS y APP_DIRS.

    Ver Loader types para más información.

  • 'string_if_invalid': la salida, como una cadena de caractéres, que el sistema de plantilla debe usar para variables no válidas (p. ej., mal escritas).

    Por defecto es una cadena de caractéres vacía.

    Ver How invalid variables are handled para más información.

  • 'file_charset': el conjunto de caracteres utilizado para leer archivos de plantilla en el disco.

    Por defecto es 'utf-8''.

  • 'bibliotecas': un diccionario de etiquetas y rutas de Python punteadas de módulos de etiquetas de plantillas para registrarse con el motor de plantillas. Esto se puede usar para agregar nuevas bibliotecas o proporcionar etiquetas alternativas para las existentes. Por ejemplo:

    OPTIONS = {
        "libraries": {
            "myapp_tags": "path.to.myapp.tags",
            "admin.urls": "django.contrib.admin.templatetags.admin_urls",
        },
    }
    

    Las bibliotecas se pueden cargar pasando la clave del diccionario correspondiente a la etiqueta {% load %}.

  • 'builtins': una lista de rutas de Python punteadas de módulos de etiquetas de plantilla para agregar a built-ins. Por ejemplo:

    OPTIONS = {
        "builtins": ["myapp.builtins"],
    }
    

    Las etiquetas y los filtros de las bibliotecas integradas se pueden usar sin llamar primero a la etiqueta {% load %}.

class Jinja2

Requiere que Jinja2 esté instalado:

$ python -m pip install Jinja2
...\> py -m pip install Jinja2

Establezca BACKEND en 'django.template.backends.jinja2.Jinja2'' para configurar un motor Jinja2.

Cuando APP_DIRS ` es ``True`, los motores Jinja2 buscan plantillas en el subdirectorio jinja2 de las aplicaciones instaladas.

La entrada más importante en OPTIONS es 'environment'. Es una ruta de Python punteada a un invocable que retorna un entorno Jinja2. Por defecto es 'jinja2.Environment'. Django invoca ese invocable y pasa otras opciones como argumentos de palabras clave. Además, Django agrega valores predeterminados que difieren de los de Jinja2 para algunas opciones:

  • 'autoescape': True
  • 'loader': un cargador configurado para DIRS y APP_DIRS
  • 'auto_reload': settings.DEBUG
  • 'undefined': DebugUndefined if settings.DEBUG else Undefined

Los motores Jinja2 también aceptan la siguiente OPTIONS:

  • 'context_processors': una lista de rutas punteadas de Python a invocables que se usan para llenar el contexto cuando una plantilla se procesa con una solicitud. Estos invocables toman un objeto de solicitud como argumento y devuelven un dict de elementos que se fusionarán en el contexto.

    Por defecto es una lista vacía.

    Se desaconseja el uso de procesadores de contexto con plantillas Jinja2.

    Los procesadores de contexto son útiles con las plantillas de Django porque las plantillas de Django no admiten funciones de llamada con argumentos. Dado que Jinja2 no tiene esa limitación, se recomienda colocar la función que usaría como procesador de contexto en las variables globales disponibles para la plantilla usando jinja2.Environment como se describe a continuación. A continuación, puede llamar a esa función en la plantilla:

    {{ function(request) }}
    

    Algunos procesadores de contexto de plantillas de Django devuelven un valor fijo. Para las plantillas de Jinja2, esta capa de direccionamiento indirecto no es necesaria ya que puede agregar constantes directamente en jinja2.Environment.

    El caso de uso original para agregar procesadores de contexto para Jinja2 involucraba:

    • Haciendo un alto consumo computacional que depende de la solicitud.
    • Necesitando el resultado en cada plantilla.
    • Usando el resultado varias veces en cada plantilla.

    A menos que se cumplan todas estas condiciones, pasar una función a la plantilla está más en línea con el diseño de Jinja2.

La configuración predeterminada se mantiene deliberadamente al mínimo. Si una plantilla se procesa con una solicitud (por ejemplo, cuando se usa render()), el backend Jinja2 agrega los globales request, csrf_input y csrf_token al contexto. Aparte de eso, este backend no crea un entorno con sabor a Django. No conoce los filtros y etiquetas de Django. Para usar las API específicas de Django, debe configurarlas en el entorno.

Por ejemplo, puede crear myproject/jinja2.py con este contenido:

from django.templatetags.static import static
from django.urls import reverse

from jinja2 import Environment


def environment(**options):
    env = Environment(**options)
    env.globals.update(
        {
            "static": static,
            "url": reverse,
        }
    )
    return env

y establezca la opción 'environment' en 'myproject.jinja2.environment'.

Entonces podría usar las siguientes construcciones en las plantillas de Jinja2:

<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">

<a href="{{ url('admin:index') }}">Administration</a>

Los conceptos de etiquetas y filtros existen tanto en el lenguaje de plantillas de Django como en Jinja2, pero se usan de manera diferente. Dado que Jinja2 admite pasar argumentos a invocables en plantillas, muchas funciones que requieren una etiqueta de plantilla o un filtro en las plantillas de Django se pueden lograr llamando a una función en las plantillas de Jinja2, como se muestra en el ejemplo anterior. El espacio de nombres global de Jinja2 elimina la necesidad de procesadores de contexto de plantilla. El lenguaje de plantillas Django no tiene un equivalente de las pruebas de Jinja2.

Back to Top