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, generaTemplateDoesNotExist
. Si se encuentra la plantilla pero contiene una sintaxis no válida, genera unTemplateSyntaxError
.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 argumentousing
.
-
select_template
(template_name_list, using=None)¶ select_template()
es comoget_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)
, dondeorigen
es un objeto `similar al origen` yestado
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, comoget_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 undict
. Si no se proporciona, el motor representará la plantilla con un contexto vacío.Si se proporciona
request
, debe ser unaHttpRequest
. 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 comoget_template()
y llama a su métodorender()
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 deget_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:
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 undict
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 esTrue
, 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 claseLoader
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 claseLoader
, y los elementos subsiguientes se pasan alLoader
durante la inicialización.El valor predeterminado depende de los valores de
DIRS
yAPP_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 paraDIRS
yAPP_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 undict
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.