Plantillas de django: incluir y extender

108

Me gustaría proporcionar el mismo contenido dentro de 2 archivos base diferentes.

Entonces estoy tratando de hacer esto:

page1.html:

{% extends "base1.html" %}
{% include "commondata.html" %}

page2.html:

{% extends "base2.html" %} 
{% include "commondata.html" %}

El problema es que parece que no puedo usar extendidos e incluidos. ¿Hay alguna forma de hacer eso? Y si no, ¿cómo puedo lograr lo anterior?

commondata.html anula un bloque que se especifica en base1.html y base2.html

El propósito de esto es proporcionar la misma página en formato pdf y html, donde el formato es ligeramente diferente. Sin embargo, la pregunta anterior simplifica lo que estoy tratando de hacer, así que si puedo obtener una respuesta, resolverá mi problema.

Ciudadano de la red
fuente

Respuestas:

110

Cuando usa la etiqueta de plantilla de extensión, está diciendo que la plantilla actual extiende a otra, que es una plantilla secundaria, que depende de una plantilla principal. Django mirará su plantilla secundaria y usará su contenido para completar la matriz.

Todo lo que desee usar en una plantilla secundaria debe estar dentro de bloques, que Django usa para completar la plantilla principal. Si desea usar una declaración de inclusión en esa plantilla secundaria, debe ponerla dentro de un bloque, para que Django le dé sentido. De lo contrario, simplemente no tiene sentido y Django no sabe qué hacer con él.

La documentación de Django tiene algunos ejemplos realmente buenos del uso de bloques para reemplazar bloques en la plantilla principal.

https://docs.djangoproject.com/en/dev/ref/templates/language/#template-inheritance

Matt Howell
fuente
1
mi commondata.html tiene el bloque definido en él. Pero no está reemplazando el bloque principal del tempalte ... Si en lugar de hacer una inclusión escribo los datos exactos dos veces tanto en page1.html como en page2.html, entonces, por supuesto, funciona. Pero quiero factorizar esa característica en común en commondata.html.
Net Citizen
Parece funcionar, recuerdo haber intentado esto, pero debí haber tenido un error tipográfico o algo en ese momento que hizo que no funcionara.
Net Citizen
1
vea mi respuesta a continuación para ver por qué no funcionó para mí la primera vez, sin embargo, lo dejo con la respuesta aceptada porque respondió la pregunta que hice correctamente.
Net Citizen
80

De los documentos de Django:

La etiqueta de inclusión debe considerarse como una implementación de "renderizar esta subplantilla e incluir el HTML", no como "analizar esta subplantilla e incluir su contenido como si fuera parte del padre". Esto significa que no hay un estado compartido entre las plantillas incluidas; cada inclusión es un proceso de representación completamente independiente.

Entonces Django no toma ningún bloque de su commondata.html y no sabe qué hacer con los bloques externos de html renderizados.

Podshumok
fuente
32

Esto debería ser el truco para usted: coloque la etiqueta de inclusión dentro de una sección de bloque.

page1.html:

{% extends "base1.html" %}

{% block foo %}
   {% include "commondata.html" %}
{% endblock %}

page2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}
Pavel Černý
fuente
1
Perfecto. Funciona para mi.
Trupti M Panchal
13

Más información sobre por qué no funcionó para mí en caso de que ayude a las personas futuras:

La razón por la que no funcionaba es que a {% include%} en django no le gustan los caracteres especiales como el elegante apóstrofe. Los datos de la plantilla que intentaba incluir se pegaron de Word. Tuve que eliminar manualmente todos estos caracteres especiales y luego se incluyeron correctamente.

Ciudadano de la red
fuente
3

No puede extraer bloques de un archivo incluido en una plantilla secundaria para anular los bloques de la plantilla principal. Sin embargo, puede especificar un padre en una variable y tener la plantilla base especificada en el contexto.

De la documentación :

{% extiende variable%} usa el valor de variable. Si la variable se evalúa como una cadena, Django usará esa cadena como el nombre de la plantilla principal. Si la variable se evalúa como un objeto Plantilla, Django usará ese objeto como plantilla principal.

En lugar de separar "page1.html" y "page2.html", colóquelo {% extends base_template %}en la parte superior de "commondata.html". Y luego, en su opinión, defina base_templateque sea "base1.html" o "base2.html".

esmeril
fuente
2

Agregado como referencia para futuras personas que encuentren esto a través de Google: es posible que desee ver la etiqueta {% overextend%} proporcionada por la biblioteca mezzanine para casos como este.

Ted
fuente
1

Edición 10 de diciembre de 2015 : como se señaló en los comentarios, ssi está en desuso desde la versión 1.8. Según la documentación:

Esta etiqueta ha quedado obsoleta y se eliminará en Django 1.10. Utilice la etiqueta de inclusión en su lugar.


En mi opinión, la (mejor) respuesta correcta a esta pregunta es la de podshumok , ya que explica por qué el comportamiento de include cuando se usa junto con la herencia.

Sin embargo, me sorprendió un poco que nadie mencionara la etiqueta ssi proporcionada por el sistema de plantillas de Django, que está diseñado específicamente para incluir un texto externo en línea . Aquí, en línea significa que el texto externo no será interpretado, analizado o interpolado, sino que simplemente "copiado" dentro de la plantilla de llamada.

Por favor, consulte la documentación para obtener más detalles (asegúrese de verificar su versión apropiada de Django en el selector en la parte inferior derecha de la página).

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ssi

De la documentación:

ssi
Outputs the contents of a given file into the page.
Like a simple include tag, {% ssi %} includes the contents of another file
 which must be specified using an absolute path  in the current page

Tenga cuidado también con las implicaciones de seguridad de esta técnica y también con la definición requerida de ALLOWED_INCLUDE_ROOTS, que debe agregarse a sus archivos de configuración.

jose.angel.jimenez
fuente
1
Tenga en cuenta que, a partir de 1.8, ssi se ha desaprobado a favor de Incluir. https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#std:templatetag-include
Tim S.