Este documento explica el sistema de plantillas de Django desde una perspectiva técnica: cómo funciona y cómo extenderlo. Si está buscando una referencia sobre la sintaxis del lenguaje, consulte El lenguaje de la plantilla de Django.

Supone una comprensión de las plantillas, los contextos, las variables, las etiquetas y la representación. Empiece con el introducción al lenguaje de plantillas de Django si no está familiarizado con estos conceptos.

Visión general

El uso del sistema de plantillas en Python es un proceso de tres pasos:

  1. Configuras un Engine.
  2. Compila el código de la plantilla en un Template.
  3. Usted renderiza la plantilla con un Context.

Los proyectos de Django generalmente se basan en API de alto nivel, agnósticas de backend para cada uno de estos pasos en lugar de las API de nivel inferior del sistema de plantillas:

  1. Para cada DjangoTemplates backend en el TEMPLATES , Django crea una instancia Engine. DjangoTemplates envuelve Engine y lo adapta a la API de backend de plantilla común.
  2. los django.template.loader módulo proporciona funciones tales como get_template() para cargar plantillas. Devuelven un django.template.backends.django.Template que envuelve el real django.template.Template.
  3. los Template obtenido en el paso anterior tiene un render() método que ordena un contexto y posiblemente una solicitud en un Context y delega la interpretación al subyacente Template.

Configurar un motor

Si está utilizando el DjangoTemplates backend, probablemente esta no sea la documentación que está buscando. Una instancia del Engine la clase descrita a continuación es accesible usando el engine El atributo de ese backend y los valores predeterminados de los atributos que se mencionan a continuación se anulan por lo que se pasa por DjangoTemplates.

class Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset="utf-8", libraries=None, builtins=None, autoescape=True)

Al crear una instancia Engine todos los argumentos deben pasarse como argumentos de palabra clave:

  • dirs es una lista de directorios donde el motor debe buscar archivos fuente de plantilla. Se utiliza para configurar filesystem.Loader.

    Por defecto es una lista vacía.

  • app_dirs solo afecta al valor predeterminado de loaders. Vea abajo.

    Por defecto es False.

  • autoescape controla si el escape automático de HTML está habilitado.

    Por defecto es True.

    Advertencia

    Solo configúrelo en False si está renderizando plantillas que no son HTML!

  • context_processors es una lista de rutas de Python con puntos a los que se pueden llamar que se utilizan para completar el contexto cuando se procesa una plantilla 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.

    Ver RequestContext para más información.

  • debug es un booleano que activa / desactiva el modo de depuración de plantilla. Si esto es True, el motor de plantillas almacenará información de depuración adicional que se puede utilizar para mostrar un informe detallado de cualquier excepción que se produzca durante la representación de la plantilla.

    Por defecto es False.

  • loaders es una lista de clases de cargadores de plantillas, especificadas como cadenas. Cada Loader la clase sabe cómo importar plantillas de una fuente en particular. Opcionalmente, se puede utilizar una tupla en lugar de una cadena. El primer elemento de la tupla debe ser el Loader nombre de la clase, los elementos subsiguientes se pasan al Loader durante la inicialización.

    Tiene como valor predeterminado una lista que contiene:

    • 'django.template.loaders.filesystem.Loader'
    • 'django.template.loaders.app_directories.Loader' si y solo si app_dirs es True.

    Si debug es False, estos cargadores están envueltos en django.template.loaders.cached.Loader.

    Ver Tipos de cargadores para detalles.

  • string_if_invalid es la salida, como una cadena, que el sistema de plantillas debe usar para las variables inválidas (por ejemplo, mal escritas).

    Por defecto es la cadena vacía.

    Ver Cómo se manejan las variables inválidas para detalles.

  • file_charset es el juego de caracteres utilizado para leer archivos de plantilla en el disco.

    Por defecto es 'utf-8'.

  • 'libraries': Un diccionario de etiquetas y rutas de Python con puntos de módulos de etiquetas de plantilla para registrar con el motor de plantillas. Esto se usa para agregar nuevas bibliotecas o proporcionar etiquetas alternativas para las existentes. Por ejemplo:

    Engine(
        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 al {% load %} etiqueta.

  • "https://foroayuda.es/django/ref/templates/builtins": Una lista de rutas de Python con puntos de módulos de etiquetas de plantilla para agregar incorporados. Por ejemplo:

    Engine(
        builtins=['myapp.builtins'],
    )
    

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

static Engine.get_default()

Devuelve el subyacente Engine desde el primer configurado DjangoTemplates motor. Eleva ImproperlyConfigured si no hay motores configurados.

Es necesario para preservar las API que dependen de un motor configurado implícitamente disponible globalmente. Se desaconseja encarecidamente cualquier otro uso.

Engine.from_string(template_code)

Compila el código de plantilla dado y devuelve un Template objeto.

Engine.get_template(template_name)

Carga una plantilla con el nombre de pila, la compila y devuelve un Template objeto.

Engine.select_template(template_name_list)

Igual que get_template(), excepto que toma una lista de nombres y devuelve la primera plantilla que se encontró.

Cargando una plantilla

La forma recomendada de crear un Template es llamando a los métodos de fábrica del Engine: get_template(), select_template() y from_string().

En un proyecto de Django donde el TEMPLATES el ajuste define un DjangoTemplates motor, es posible crear una instancia Template directamente. Si mas de uno DjangoTemplates motor está definido, se utilizará el primero.

class Template

Esta clase vive en django.template.Template. El constructor toma un argumento: el código de plantilla sin formato:

from django.template import Template

template = Template("My name is {{ my_name }}.")

Entre bastidores

El sistema solo analiza el código de la plantilla sin procesar una vez, cuando crea el Template objeto. A partir de ese momento, se almacena internamente como una estructura de árbol para el rendimiento.

Incluso el análisis en sí es bastante rápido. La mayor parte del análisis se realiza mediante una única llamada a una única expresión regular corta.

Representar un contexto

Una vez que haya compilado Template objeto, puede representar un contexto con él. Puede reutilizar la misma plantilla para renderizarla varias veces con diferentes contextos.

class Context(dict_=None)

El constructor de django.template.Context toma un argumento opcional: un diccionario que asigna nombres de variables a valores de variables.

Para obtener más detalles, consulte Jugando con objetos de contexto debajo.

Template.render(context)

Llama a Template objetos render() método con un Context para “llenar” la plantilla:

>>> from django.template import Context, Template
>>> template = Template("My name is {{ my_name }}.")

>>> context = Context({"my_name": "Adrian"})
>>> template.render(context)
"My name is Adrian."

>>> context = Context({"my_name": "Dolores"})
>>> template.render(context)
"My name is Dolores."

Variables y búsquedas

Los nombres de las variables deben constar de cualquier letra (AZ), cualquier dígito (0-9), un guión bajo (pero no deben comenzar con un guión bajo) o un punto.

Los puntos tienen un significado especial en la representación de plantillas. Un punto en el nombre de una variable significa buscar. Específicamente, cuando el sistema de plantillas encuentra un punto en el nombre de una variable, intenta las siguientes búsquedas, en este orden:

  • Búsqueda de diccionario. Ejemplo: foo["bar"]
  • Búsqueda de atributos. Ejemplo: foo.bar
  • Búsqueda de índice de lista. Ejemplo: foo[bar]

Tenga en cuenta que “barra” en una expresión de plantilla como {{ foo.bar }} se interpretará como una cadena literal y sin utilizar el valor de la variable “bar”, si existe alguna en el contexto de la plantilla.

El sistema de plantillas utiliza el primer tipo de búsqueda que funciona. Es lógica de cortocircuito. Aquí están algunos ejemplos:

>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."

>>> class PersonClass: pass
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."

>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."

Si alguna parte de la variable es invocable, el sistema de plantillas intentará llamarla. Ejemplo:

>>> class PersonClass2:
...     def name(self):
...         return "Samantha"
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."

Las variables invocables son un poco más complejas que las variables que solo requieren búsquedas directas. A continuación, se incluyen algunas cosas a tener en cuenta:

  • Si la variable genera una excepción cuando se llama, la excepción se propagará, a menos que la excepción tenga un atributo silent_variable_failure cuyo valor es True. Si la excepcion lo hace tener un silent_variable_failure atributo cuyo valor es True, la variable se representará como el valor del motor string_if_invalid opción de configuración (una cadena vacía, por defecto). Ejemplo:

    >>> t = Template("My name is {{ person.first_name }}.")
    >>> class PersonClass3:
    ...     def first_name(self):
    ...         raise AssertionError("foo")
    >>> p = PersonClass3()
    >>> t.render(Context({"person": p}))
    Traceback (most recent call last):
    ...
    AssertionError: foo
    
    >>> class SilentAssertionError(Exception):
    ...     silent_variable_failure = True
    >>> class PersonClass4:
    ...     def first_name(self):
    ...         raise SilentAssertionError
    >>> p = PersonClass4()
    >>> t.render(Context({"person": p}))
    "My name is ."
    

    Tenga en cuenta que django.core.exceptions.ObjectDoesNotExist, que es la clase base para todas las API de base de datos de Django DoesNotExist excepciones, tiene silent_variable_failure = True. Entonces, si está usando plantillas de Django con objetos de modelo de Django, cualquier DoesNotExist la excepción fallará silenciosamente.

  • Solo se puede llamar a una variable si no tiene argumentos requeridos. De lo contrario, el sistema devolverá el valor del motor string_if_invalid opción.
  • Puede haber efectos secundarios al llamar a algunas variables, y sería una tontería o un agujero de seguridad permitir que el sistema de plantillas acceda a ellas.

    Un buen ejemplo es el delete() en cada objeto de modelo de Django. No se debe permitir que el sistema de plantillas haga algo como esto:

    I will now delete this valuable data. {{ data.delete }}
    

    Para evitar esto, establezca un alters_data atributo en la variable invocable. El sistema de plantillas no llamará a una variable si tiene alters_data=True set, y en su lugar reemplazará la variable con string_if_invalid, incondicionalmente. El generado dinámicamente delete() y save() los métodos en los objetos del modelo de Django obtienen alters_data=True automáticamente. Ejemplo:

    def sensitive_function(self):
        self.database_record.delete()
    sensitive_function.alters_data = True
    
  • Ocasionalmente, es posible que desee desactivar esta función por otras razones y decirle al sistema de plantillas que deje una variable sin llamar sin importar qué. Para hacerlo, establezca un do_not_call_in_templates atributo en el invocable con el valor True. El sistema de plantilla actuará como si su variable no fuera invocable (permitiéndole acceder a los atributos de la invocable, por ejemplo).

Cómo se manejan las variables inválidas

Generalmente, si una variable no existe, el sistema de plantillas inserta el valor del motor string_if_invalid opción de configuración, que se establece en '' (la cadena vacía) de forma predeterminada.

Los filtros que se aplican a una variable no válida solo se aplicarán si string_if_invalid se establece en '' (la cadena vacía). Si string_if_invalid se establece en cualquier otro valor, los filtros de variables se ignorarán.

Este comportamiento es ligeramente diferente para el if, for y regroup etiquetas de plantilla. Si se proporciona una variable no válida a una de estas etiquetas de plantilla, la variable se interpretará como None. Los filtros siempre se aplican a las variables no válidas dentro de estas etiquetas de plantilla.

Si string_if_invalid contiene una '%s', el marcador de formato se reemplazará con el nombre de la variable no válida.

¡Solo con fines de depuración!

Tiempo string_if_invalid puede ser una herramienta de depuración útil, es una mala idea activarla como un “valor predeterminado de desarrollo”.

Muchas plantillas, incluidas algunas de Django, dependen del silencio del sistema de plantillas cuando se encuentra una variable inexistente. Si asigna un valor que no sea '' para string_if_invalid, experimentará problemas de representación con estas plantillas y sitios.

Generalmente, string_if_invalid solo debe habilitarse para depurar un problema de plantilla específico, luego borrarse una vez que se completa la depuración.

Variables integradas

Cada contexto contiene True, False y None. Como era de esperar, estas variables se resuelven en los correspondientes objetos de Python.

Limitaciones con cadenas literales

El lenguaje de plantilla de Django no tiene forma de escapar de los caracteres utilizados para su propia sintaxis. Por ejemplo, el templatetag La etiqueta es necesaria si necesita generar secuencias de caracteres como {% y %}.

Existe un problema similar si desea incluir estas secuencias en filtros de plantilla o argumentos de etiquetas. Por ejemplo, al analizar una etiqueta de bloque, el analizador de plantillas de Django busca la primera aparición de %} después de {%. Esto evita el uso de "%}" como una cadena literal. Por ejemplo, un TemplateSyntaxError se generará para las siguientes expresiones:

{% include "template.html" tvar="Some string literal with %} in it." %}

{% with tvar="Some string literal with %} in it." %}{% endwith %}

El mismo problema se puede desencadenar mediante el uso de una secuencia reservada en los argumentos de filtro:

{{ some.variable|default:"}}" }}

Si necesita utilizar cadenas con estas secuencias, guárdelas en variables de plantilla o utilice una etiqueta de plantilla personalizada o un filtro para solucionar la limitación.

Jugando con Context objetos

La mayoría de las veces, creará una instancia Context objetos pasando en un diccionario completamente poblado a Context(). Pero puede agregar y eliminar elementos de un Context objeto una vez que se ha creado una instancia, también, utilizando la sintaxis de diccionario estándar:

>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
Context.get(key, otherwise=None)

Devuelve el valor de key si key está en el contexto, de lo contrario regresa otherwise.

Context.setdefault(key, default=None)

Si key está en el contexto, devuelve su valor. De lo contrario inserta key con un valor de default y vuelve default.

Context.pop()
Context.push()
exception ContextPopException

A Context el objeto es una pila. Es decir, puedes push() y pop() eso. Si tu pop() demasiado, subirá django.template.ContextPopException:

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.push()
{}
>>> c['foo'] = 'second level'
>>> c['foo']
'second level'
>>> c.pop()
{'foo': 'second level'}
>>> c['foo']
'first level'
>>> c['foo'] = 'overwritten'
>>> c['foo']
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
ContextPopException

También puedes usar push() como administrador de contexto para asegurar una coincidencia pop() se llama.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.push():
...     c['foo'] = 'second level'
...     c['foo']
'second level'
>>> c['foo']
'first level'

Todos los argumentos pasados ​​a push() será pasado a la dict constructor utilizado para construir el nuevo nivel de contexto.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.push(foo='second level'):
...     c['foo']
'second level'
>>> c['foo']
'first level'
Context.update(other_dict)

Además de push() y pop(), los Context El objeto también define un update() método. Esto funciona como push() pero toma un diccionario como argumento y empuja ese diccionario a la pila en lugar de uno vacío.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'foo': 'updated'})
{'foo': 'updated'}
>>> c['foo']
'updated'
>>> c.pop()
{'foo': 'updated'}
>>> c['foo']
'first level'

Igual que push(), puedes usar update() como administrador de contexto para asegurar una coincidencia pop() se llama.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> with c.update({'foo': 'second level'}):
...     c['foo']
'second level'
>>> c['foo']
'first level'

Usando un Context como una pila es útil en algunas etiquetas de plantilla personalizadas.

Context.flatten()

Utilizando flatten() método que puedes conseguir completo Context apilar como un diccionario que incluye variables integradas.

>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.update({'bar': 'second level'})
{'bar': 'second level'}
>>> c.flatten()
{'True': True, 'None': None, 'foo': 'first level', 'False': False, 'bar': 'second level'}

A flatten() El método también se utiliza internamente para hacer Context objetos comparables.

>>> c1 = Context()
>>> c1['foo'] = 'first level'
>>> c1['bar'] = 'second level'
>>> c2 = Context()
>>> c2.update({'bar': 'second level', 'foo': 'first level'})
{'foo': 'first level', 'bar': 'second level'}
>>> c1 == c2
True

El resultado de flatten() puede ser útil en pruebas unitarias para comparar Context contra dict:

class ContextTest(unittest.TestCase):
    def test_against_dictionary(self):
        c1 = Context()
        c1['update'] = 'value'
        self.assertEqual(c1.flatten(), {
            'True': True,
            'None': None,
            'False': False,
            'update': 'value',
        })

Utilizando RequestContext

class RequestContext(request, dict_=None, processors=None)

Django viene con un especial Context clase, django.template.RequestContext, que actúa de forma ligeramente diferente a la normal django.template.Context. La primera diferencia es que se necesita un HttpRequest como su primer argumento. Por ejemplo:

c = RequestContext(request, {
    'foo': 'bar',
})

La segunda diferencia es que llena automáticamente el contexto con algunas variables, de acuerdo con el motor context_processors opción de configuración.

los context_processors La opción es una lista de personas que se pueden llamar, llamada procesadores de contexto – que toman un objeto de solicitud como argumento y devuelven un diccionario de elementos para fusionarlos en el contexto. En el archivo de configuración generado por defecto, el motor de plantilla predeterminado contiene los siguientes procesadores de contexto:

[
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
]

Además de estos, RequestContext siempre habilita 'django.template.context_processors.csrf'. Este es un procesador de contexto relacionado con la seguridad requerido por el administrador y otras aplicaciones contrib y, en caso de una mala configuración accidental, está deliberadamente codificado y no se puede apagar en el context_processors opción.

Cada procesador se aplica en orden. Eso significa que si un procesador agrega una variable al contexto y un segundo procesador agrega una variable con el mismo nombre, el segundo anulará al primero. Los procesadores predeterminados se explican a continuación.

Cuando se aplican procesadores de contexto

Los procesadores de contexto se aplican sobre los datos de contexto. Esto significa que un procesador de contexto puede sobrescribir las variables que ha proporcionado a su Context o RequestContext, así que tenga cuidado de evitar nombres de variables que se superpongan con los proporcionados por sus procesadores de contexto.

Si desea que los datos de contexto tengan prioridad sobre los procesadores de contexto, utilice el siguiente patrón:

from django.template import RequestContext

request_context = RequestContext(request)
request_context.push({"my_name": "Adrian"})

Django hace esto para permitir que los datos de contexto anulen los procesadores de contexto en API como render() y TemplateResponse.

Además, puedes dar RequestContext una lista de procesadores adicionales, utilizando el tercer argumento posicional opcional, processors. En este ejemplo, el RequestContext instancia obtiene una ip_address variable:

from django.http import HttpResponse
from django.template import RequestContext, Template

def ip_address_processor(request):
    return {'ip_address': request.META['REMOTE_ADDR']}

def client_ip_view(request):
    template = Template('{{ title }}: {{ ip_address }}')
    context = RequestContext(request, {
        'title': 'Your IP Address',
    }, [ip_address_processor])
    return HttpResponse(template.render(context))

Procesadores de contexto de plantilla integrados

Esto es lo que hace cada uno de los procesadores integrados:

django.contrib.auth.context_processors.auth

auth()

Si este procesador está habilitado, cada RequestContext contendrá estas variables:

  • user – Un auth.User instancia que representa al usuario actualmente conectado (o un AnonymousUser ejemplo, si el cliente no ha iniciado sesión).
  • perms – Una instancia de django.contrib.auth.context_processors.PermWrapper, que representa los permisos que tiene el usuario actualmente conectado.

django.template.context_processors.debug

debug()

Si este procesador está habilitado, cada RequestContext contendrá estas dos variables, pero solo si su DEBUG la configuración está establecida en True y la dirección IP de la solicitud (request.META['REMOTE_ADDR']) está en el INTERNAL_IPS configuración:

  • debugTrue. Puede usar esto en plantillas para probar si está en DEBUG modo.
  • sql_queries – Una lista de {'sql': ..., 'time': ...} diccionarios, que representan cada consulta SQL que ha ocurrido hasta ahora durante la solicitud y cuánto tiempo ha tardado. La lista está ordenada por alias de la base de datos y luego por consulta. Se genera perezosamente en el acceso.

django.template.context_processors.i18n

i18n()

Si este procesador está habilitado, cada RequestContext contendrá estas variables:

  • LANGUAGES – El valor de la LANGUAGES configuración.
  • LANGUAGE_BIDITrue si el idioma actual es un idioma de derecha a izquierda, por ejemplo, hebreo, árabe. False si es un idioma de izquierda a derecha, por ejemplo, inglés, francés, alemán.
  • LANGUAGE_CODErequest.LANGUAGE_CODE, si existiera. De lo contrario, el valor de la LANGUAGE_CODE configuración.

Ver Etiquetas de plantilla i18n para etiquetas de plantilla que generan los mismos valores.

django.template.context_processors.media

Si este procesador está habilitado, cada RequestContext contendrá una variable MEDIA_URL, proporcionando el valor de la MEDIA_URL configuración.

django.template.context_processors.static

static()

Si este procesador está habilitado, cada RequestContext contendrá una variable STATIC_URL, proporcionando el valor de la STATIC_URL configuración.

django.template.context_processors.csrf

Este procesador agrega un token que necesita el csrf_token etiqueta de plantilla para protección contra Falsificaciones de solicitudes entre sitios.

django.template.context_processors.request

Si este procesador está habilitado, cada RequestContext contendrá una variable request, que es la actual HttpRequest.

django.template.context_processors.tz

tz()

Si este procesador está habilitado, cada RequestContext contendrá una variable TIME_ZONE, proporcionando el nombre de la zona horaria actualmente activa.

django.contrib.messages.context_processors.messages

Si este procesador está habilitado, cada RequestContext contendrá estas dos variables:

  • messages – Una lista de mensajes (como cadenas) que se han configurado a través del marco de mensajes.
  • DEFAULT_MESSAGE_LEVELS – Un mapeo de los nombres de nivel de mensaje a su valor numérico.

Escribir sus propios procesadores de contexto

Un procesador de contexto tiene una interfaz simple: es una función de Python que toma un argumento, un HttpRequest objeto y devuelve un diccionario que se agrega al contexto de la plantilla.

Por ejemplo, para agregar el DEFAULT_FROM_EMAIL ajuste a cada contexto:

from django.conf import settings

def from_email(request):
    return {
        "DEFAULT_FROM_EMAIL": settings.DEFAULT_FROM_EMAIL,
    }

Los procesadores de contexto personalizados pueden vivir en cualquier lugar de su base de código. Todo lo que le importa a Django es que sus procesadores de contexto personalizados estén apuntados por el 'context_processors' opción en tu TEMPLATES ajuste – o el context_processors argumento de Engine si lo está usando directamente.

Cargando plantillas

Generalmente, almacenará las plantillas en archivos en su sistema de archivos en lugar de usar el nivel bajo Template API usted mismo. Guarde las plantillas en un directorio especificado como directorio de plantillas.

Django busca directorios de plantillas en varios lugares, dependiendo de la configuración de carga de su plantilla (consulte “Tipos de cargadores” a continuación), pero la forma más básica de especificar directorios de plantillas es mediante el uso de DIRS opción.

los DIRS opción

Dígale a Django cuáles son sus directorios de plantillas usando el DIRS opción en el TEMPLATES en su archivo de configuración – o el dirs argumento de Engine. Esto debe establecerse en una lista de cadenas que contengan rutas completas a los directorios de su plantilla:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            '/home/html/templates/lawrence.com',
            '/home/html/templates/default',
        ],
    },
]

Sus plantillas pueden ir a cualquier lugar que desee, siempre que el servidor web pueda leer los directorios y las plantillas. Pueden tener cualquier extensión que desee, como .html o .txto no pueden tener ninguna extensión.

Tenga en cuenta que estas rutas deben usar barras diagonales de estilo Unix, incluso en Windows.

Tipos de cargadores

De forma predeterminada, Django usa un cargador de plantillas basado en el sistema de archivos, pero Django viene con algunos otros cargadores de plantillas, que saben cómo cargar plantillas de otras fuentes.

Algunos de estos otros cargadores están deshabilitados de forma predeterminada, pero puede activarlos agregando un 'loaders' opción a tu DjangoTemplates backend en el TEMPLATES establecer o pasar un loaders argumento para Engine. loaders debe ser una lista de cadenas o tuplas, donde cada una representa una clase de cargador de plantillas. Aquí están los cargadores de plantillas que vienen con Django:

django.template.loaders.filesystem.Loader

class filesystem.Loader

Carga plantillas del sistema de archivos, de acuerdo con DIRS.

Este cargador está habilitado de forma predeterminada. Sin embargo, no encontrará ninguna plantilla hasta que establezca DIRS a una lista no vacía:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [BASE_DIR / 'templates'],
}]

También puede anular 'DIRS' y especificar directorios específicos para un cargador de sistema de archivos en particular:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'OPTIONS': {
        'loaders': [
            (
                'django.template.loaders.filesystem.Loader',
                [BASE_DIR / 'templates'],
            ),
        ],
    },
}]

django.template.loaders.app_directories.Loader

class app_directories.Loader

Carga plantillas de aplicaciones Django en el sistema de archivos. Para cada aplicación en INSTALLED_APPS, el cargador busca un templates subdirectorio. Si el directorio existe, Django busca plantillas allí.

Esto significa que puede almacenar plantillas con sus aplicaciones individuales. Esto también ayuda a distribuir aplicaciones de Django con plantillas predeterminadas.

Por ejemplo, para esta configuración:

INSTALLED_APPS = ['myproject.polls', 'myproject.music']

…luego get_template('foo.html') buscará foo.html en estos directorios, en este orden:

  • /path/to/myproject/polls/templates/
  • /path/to/myproject/music/templates/

… Y usará el que encuentre primero.

El orden de INSTALLED_APPS ¡es significante! Por ejemplo, si desea personalizar el administrador de Django, puede optar por anular el estándar admin/base_site.html plantilla, de django.contrib.admin, contigo mismo admin/base_site.html en myproject.polls. A continuación, debe asegurarse de que su myproject.polls proviene antes de django.contrib.admin en INSTALLED_APPS, de lo contrario django.contrib.adminLas de primero se cargarán y las suyas se ignorarán.

Tenga en cuenta que el cargador realiza una optimización cuando se ejecuta por primera vez: almacena en caché una lista de los INSTALLED_APPS los paquetes tienen un templates subdirectorio.

Puede habilitar este cargador configurando APP_DIRS para True:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'APP_DIRS': True,
}]

django.template.loaders.cached.Loader

class cached.Loader

Por defecto (cuando DEBUG es True), el sistema de plantillas lee y compila sus plantillas cada vez que se procesan. Si bien el sistema de plantillas de Django es bastante rápido, la sobrecarga de leer y compilar plantillas puede sumarse.

Configura el cargador de plantillas en caché con una lista de otros cargadores que debe envolver. Los cargadores envueltos se utilizan para localizar plantillas desconocidas cuando se encuentran por primera vez. El cargador en caché luego almacena el compilado Template en memoria. El caché Template La instancia se devuelve para solicitudes posteriores para cargar la misma plantilla.

Este cargador se habilita automáticamente si OPTIONS['loaders'] no está especificado y OPTIONS['debug'] es False (la última opción tiene por defecto el valor de DEBUG).

También puede habilitar el almacenamiento en caché de plantillas con algunos cargadores de plantillas personalizados usando configuraciones como esta:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [BASE_DIR / 'templates'],
    'OPTIONS': {
        'loaders': [
            ('django.template.loaders.cached.Loader', [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
                'path.to.custom.Loader',
            ]),
        ],
    },
}]

Nota

Todas las etiquetas de plantilla de Django integradas son seguras de usar con el cargador en caché, pero si está utilizando etiquetas de plantilla personalizadas que provienen de paquetes de terceros, o que usted mismo escribió, debe asegurarse de que el Node La implementación de cada etiqueta es segura para subprocesos. Para más información, ver Consideraciones de seguridad de subprocesos de etiquetas de plantilla.

django.template.loaders.locmem.Loader

class locmem.Loader

Carga plantillas de un diccionario de Python. Esto es útil para realizar pruebas.

Este cargador toma un diccionario de plantillas como primer argumento:

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'OPTIONS': {
        'loaders': [
            ('django.template.loaders.locmem.Loader', {
                'index.html': 'content here',
            }),
        ],
    },
}]

Este cargador está desactivado de forma predeterminada.

Django usa los cargadores de plantillas en orden de acuerdo con 'loaders' opción. Utiliza cada cargador hasta que un cargador encuentra una coincidencia.

Cargadores personalizados

Es posible cargar plantillas de fuentes adicionales utilizando cargadores de plantillas personalizados. Personalizado Loader las clases deben heredar de django.template.loaders.base.Loader y definir el get_contents() y get_template_sources() métodos.

Métodos de cargador

class Loader

Carga plantillas de una fuente determinada, como el sistema de archivos o una base de datos.

get_template_sources(template_name)

Un método que requiere template_name y rinde Origin instancias para cada fuente posible.

Por ejemplo, el cargador del sistema de archivos puede recibir 'index.html' como un template_name argumento. Este método daría origen a la ruta completa de index.html como aparece en cada directorio de plantillas que mira el cargador.

El método no necesita verificar que la plantilla exista en una ruta determinada, pero debe garantizar que la ruta sea válida. Por ejemplo, el cargador del sistema de archivos se asegura de que la ruta se encuentre en un directorio de plantilla válido.

get_contents(origin)

Devuelve el contenido de una plantilla dada una Origin ejemplo.

Aquí es donde un cargador del sistema de archivos leería el contenido del sistema de archivos, o un cargador de la base de datos leería de la base de datos. Si no existe una plantilla coincidente, esto debería generar un TemplateDoesNotExist error.

get_template(template_name, skip=None)

Devuelve un Template objeto para un dado template_name recorriendo los resultados de get_template_sources() y llamando get_contents(). Esto devuelve la primera plantilla coincidente. Si no se encuentra ninguna plantilla, TemplateDoesNotExist es elevado.

El opcional skip El argumento es una lista de orígenes que se deben ignorar al extender plantillas. Esto permite que las plantillas amplíen otras plantillas del mismo nombre. También se utiliza para evitar errores de recursividad.

En general, basta con definir get_template_sources() y get_contents() para cargadores de plantillas personalizadas. get_template() normalmente no será necesario anularlo.

Construyendo tu propio

Por ejemplo, lea el código fuente para los cargadores integrados de Django.

Origen de la plantilla

Las plantillas tienen un origin que contienen atributos según la fuente desde la que se cargan.

class Origin(name, template_name=None, loader=None)
name

La ruta a la plantilla devuelta por el cargador de plantillas. Para los cargadores que leen desde el sistema de archivos, esta es la ruta completa a la plantilla.

Si se crea una instancia de la plantilla directamente en lugar de a través de un cargador de plantillas, este es un valor de cadena de <unknown_source>.

template_name

La ruta relativa a la plantilla que se pasó al cargador de plantillas.

Si se crea una instancia de la plantilla directamente en lugar de a través de un cargador de plantillas, esto es None.

loader

La instancia del cargador de plantillas que construyó este Origin.

Si se crea una instancia de la plantilla directamente en lugar de a través de un cargador de plantillas, esto es None.

django.template.loaders.cached.Loader requiere que todos sus cargadores envueltos establezcan este atributo, por lo general creando una instancia del Origin con loader=self.