2012-04-03 13 views
25

Me pregunto si alguien sabe cómo lidiar con la siguiente estructura de la plantilla peculiar:las plantillas de Django: bloques superior de los niños incluidos plantillas a través de una plantilla extendida

### base.html 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> 
<html lang="en"> 

<head> 
    <title> {% block title %} Title of the page {% endblock %} </title> 
</head> 

<body> 
    <header> 
    {% block header %} 
     {% include "base/header.html" %} 
    {% endblock header %} 
    </header> 
    {% block content %}{% endblock %} 
</body> 

</html> 

### base/header.html 
<div id="menu-bar"> 
    {% block nav %} 
    {% include "base/nav.html" %} 
    {% endblock %} 
</div> 

### base/nav.html 
<nav id="menu"> 
    <ul> 
    <li> 
     <a href="/profile/">My Profile</a> 
    </li> 
    <li> 
     <a href="/favs/">My Favorites</a> 
    </li> 
    {% block extra-content %}{% endblock %} 
    </ul> 
</nav> 

Y, el corazón de la cuestión:


### app/somepage.html 
{% extends "base.html" %} 
{% block content %} 
    <p>Content is overridden!</p> 
{% endblock %} 

{% block extra-content %} 
    <p>This will not show up, though...</p> 
{% endblock %} 

{% block nav %} 
    <p>Not even this.</p> 
{% endblock %} 

El problema es que al extender una plantilla solo puede anular los bloques declarados solo en el elemento primario, no en ninguno de sus elementos secundarios.

Supongo que podría hacer que base.html sea una cáscara de bloques anidados no utilizados vacíos que cubran todas las contingencias futuras, pero ¿incluso eso anularía correctamente? ¿Y esa es la única forma?

Si se está preguntando por qué tengo un flujo de trabajo include/extends bidireccional en base.html, tengo muchas subpáginas que quiero usar en todo el proyecto: encabezados, pies de página, navs, barras laterales, etc. Todos serán consistentes en la estructura en todo el sitio, pero en muchos casos una subdivisión completa del sitio solo necesitará algunas de esas subpáginas. Mi idea era definir las subpáginas en la carpeta templates/base, y tener templates/base-type1.html, templates/base-type2.html, etc. para ampliar en otros lugares. Cada tipo solo haría referencia a las plantillas secundarias necesarias, y las anularía para colocar el contenido según sea necesario.

+1

Bueno, después de registrar veo [esta cuestión] (http://stackoverflow.com/questions/9034331/overwriting-a-block-within-an- Plantilla-incluida-de-una-plantilla-extendida) aparece en la barra lateral, incluso después de una búsqueda exhaustiva de desbordamiento de pila y búsqueda en Google. Entiendo la mecánica de esta limitación en django, pero, amigo, las implicaciones son deprimentes. –

+0

Totalmente intentado publicar esto como una respuesta, pero mi nueva cuenta de pila carece del representante ... Olvidé sobre eso. –

+0

Para futuros buscadores: la [pregunta antes mencionada] (http://stackoverflow.com/questions/9034331/overwriting-a-block-within-an-included-template-from-an-extended-template) tiene una muestra de código básico algunas respuestas abajo demostrando la estrategia útil de @ Marcin. –

Respuesta

5

Puede resolver esto ampliando sus plantillas incluidas actualmente, y luego incluyendo la extensión en lugar de la plantilla base actualmente incluida.

+0

Su solución funcionaría si solo tuviera una jerarquía lineal de plantillas, como en el ejemplo anterior. IRL mi situación es una jerarquía de bifurcación con base.html como el tronco del árbol.Como se mencionó brevemente, también incluye un pie de página, una barra lateral, etc. lo que significa que no puedo simplemente voltear la dirección de inclusión y extender el encabezado. –

+0

@ChrisKeele Siempre que su inclusión esté en un bloque, puede reemplazar el incluir con la inclusión de una plantilla derivada, así que sí, esto funcionaría. – Marcin

+0

Así que si tuviera un header.html y un footer.html, haría cada extensión base.html, luego en example.html ... ¿Qué? ¿Incluyendo el encabezado y los pies de página? ¿Y extendiendo la base encima de eso? Lo siento por necesitar más aclaraciones, pero ahora estoy lejos del código, y "reemplazar el include con la inclusión de una plantilla derivada" es difícil de imaginar sin un sandbox. :) –

23

parece ser poco conocido que se puede utilizar la palabra clave with con el include para pasar variables en el contexto de una plantilla incluida - se puede usar para especificar incluye en la plantilla incluye:

# base.html 
<html> 
    <body> 
     {% block header %}{% include "header.html" %}{% endblock %} 
    </body> 
</html> 

# header.html 
# some stuff here 
<div id="header"> 
    <img src="logo.png"> 
    {% include nav_tmpl|default:"navigation.html" %} 
</div> 

# special_page.html (uses other navigation) 
{% extends "base.html" %} 
{% block header %} 
    {% include "header.html" with nav_tmpl="special_nav.html" %} 
    # you might also want to wrap the include in an 'if' tag if you don't want anything 
    # included here per default 
{% endblock %} 

Este enfoque le ahorra al menos tener un archivo adicional solo con el fin de sobrescribir un bloque. También puede usar la palabra clave with para pasar un valor a través de una jerarquía más grande de includes también.

9

Una variante más concisa a la solution proposed by @Bernhard Vallant:

# base.html 
<html> 
    <body> 
     {% block header %}{% include "header.html" %}{% endblock %} 
    </body> 
</html> 

# header.html 
# some stuff here 
<div id="header"> 
    <img src="logo.png"> 
    {% include nav_tmpl|default:"navigation.html" %} 
</div> 

# special_page.html (uses other navigation) 
{% extends "base.html" %} 
{% block header %} 
    {% with nav_tmpl="special_nav.html" %} 
     {{ block.super }} 
    {% endwith %} 
{% endblock %} 
Cuestiones relacionadas