2012-04-03 4 views
25

mi chiedo se qualcuno sa come trattare con la seguente struttura modello eccentrico:Django modelli: blocchi imperativi di bambini inclusi templates attraverso un modello esteso

### 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> 

E, il nocciolo della questione:


### 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 %} 

Il problema è quando si estende un modello è possibile ignorare solo i blocchi dichiarati nel genitore solo, non uno dei suoi figli.

Suppongo che potrei rendere base.html un guscio di blocchi nidificati vuoti inutilizzati che coprono tutte le contingenze future, ma anche che sovrascriverà correttamente? Ed è questo l'unico modo?

Se ti stai chiedendo perché ho un flusso di lavoro bidirezionale/esteso attorno a base.html, ho molti sotto-modelli che voglio utilizzare in tutto il progetto: Intestazioni, piè di pagina, nav, barre laterali, ecc. Saranno tutti coerenti nella struttura dell'intero sito, ma in molti casi un'intera suddivisione del sito avrà bisogno solo di alcuni di questi sotto-modelli. La mia idea era di definire i sotto-modelli sotto la cartella templates/base, e avere template/base-type1.html, templates/base-type2.html, ecc. Per estendersi in altri posti. Ogni tipo farebbe solo riferimento ai sotto-modelli necessari e li sovrascriverà per posizionare il contenuto secondo necessità.

+1

Ebbene, dopo la pubblicazione vedo [questa domanda] (http://stackoverflow.com/questions/9034331/overwriting-a-block-within-an- incluso-template-from-an-extended-template) compare nella barra laterale, anche dopo una ricerca approfondita di overflow dello stack e googling. Capisco la meccanica di questa limitazione nel django, ma l'uomo, le implicazioni sono deprimenti. –

+0

Totalmente provato a postare questo come una risposta, ma il mio nuovo account stack manca la risposta ... Dimenticato di questo. –

+0

Per i cercatori futuri: la [domanda di cui sopra] (http://stackoverflow.com/questions/9034331/overwriting-a-block-within-an-included-template-from-an-extended-template) ha un esempio di codice di base alcune risposte giù dimostrando la strategia utile di @ Marcin. –

risposta

5

È possibile risolvere questo problema estendendo i modelli attualmente inclusi, quindi includendo l'estensione anziché il modello base attualmente incluso.

+0

La tua soluzione funzionerebbe se avessi solo una gerarchia lineare di modelli, come nell'esempio di bare-bones sopra. IRL la mia situazione è una gerarchia ramificata con base.html come tronco dell'albero.Come accennato brevemente, include anche un piè di pagina, una barra laterale, ecc; il che significa che non posso semplicemente capovolgere la direzione di inclusione ed estendere l'intestazione. –

+0

@ChrisKeele Finché l'inclusione è in un blocco, è possibile sostituire l'inclusione con l'inclusione di un modello derivato, quindi sì, funzionerebbe. – Marcin

+0

Quindi se avessi un header.html e un footer.html, farei ogni estensione base.html, poi in example.html ... Fai cosa? Compresi l'intestazione e i piè di pagina? E estendendo la base in cima a quello? Ci scusiamo per aver bisogno di ulteriori chiarimenti, ma in questo momento sono lontano dal codice e "sostituire l'inclusione con l'inclusione di un modello derivato" è difficile per me immaginare senza sandbox. :) –

23

Sembra essere poco conosciuto che è possibile utilizzare la parola chiave with con il include per passare le variabili nel contesto di un modello incluso - è possibile utilizzarlo per specificare comprende nel modello incluso:

# 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 %} 

Questo approccio ti consente almeno di avere un file aggiuntivo solo per sovrascrivere un blocco. È inoltre possibile utilizzare la parola chiave with per passare un valore attraverso una gerarchia più ampia di include.

9

Una variante terser al 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 %}