template django: include ed estende


108

Vorrei fornire lo stesso contenuto all'interno di 2 file di base diversi.

Quindi sto cercando di fare questo:

page1.html:

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

page2.html:

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

Il problema è che non riesco a usare sia le estensioni che le include. C'è un modo per farlo? E se no, come posso realizzare quanto sopra?

commondata.html sostituisce un blocco specificato sia in base1.html che in base2.html

Lo scopo di questo è fornire la stessa pagina sia in formato pdf che in formato html, dove la formattazione è leggermente diversa. La domanda sopra però semplifica ciò che sto cercando di fare, quindi se riesco a ottenere una risposta risolverà il mio problema.

Risposte:


110

Quando usi il tag del modello extends, stai dicendo che il modello corrente ne estende un altro: che è un modello figlio, dipendente da un modello principale. Django esaminerà il tuo modello figlio e utilizzerà il suo contenuto per popolare il genitore.

Tutto quello che vuoi usare in un template figlio dovrebbe essere all'interno di blocchi, che Django usa per popolare il genitore. Se vuoi usare un'istruzione include in quel template figlio, devi metterla all'interno di un blocco, affinché Django abbia un senso. Altrimenti non ha senso e Django non sa cosa farne.

La documentazione di Django ha alcuni ottimi esempi di utilizzo dei blocchi per sostituire i blocchi nel template genitore.

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


1
my commondata.html ha il blocco definito in esso. Ma non sta sostituendo il blocco del genitore tempalte ... Se invece di fare un'inclusione scrivo i dati esatti due volte sia in page1.html che in page2.html, ovviamente funziona. Ma voglio scomporre questa comunanza in commondata.html.
Net Citizen

Sembra funzionare, ricordo di aver provato questo ma devo aver avuto un errore di battitura o qualcosa del genere al momento che non ha funzionato.
Net Citizen

1
vedi la mia risposta di seguito per il motivo per cui non ha funzionato per me la prima volta, ti lascio con la risposta accettata però perché hai risposto correttamente alla domanda che ho posto.
Net Citizen

80

Dai documenti di Django:

Il tag include dovrebbe essere considerato come un'implementazione di "visualizza questo subtemplate e includi HTML", non come "analizza questo subtemplate e includi i suoi contenuti come se fosse parte del genitore". Ciò significa che non esiste uno stato condiviso tra i modelli inclusi: ogni inclusione è un processo di rendering completamente indipendente.

Quindi Django non prende alcun blocco dal tuo commondata.html e non sa cosa fare con i blocchi html renderizzati all'esterno.


32

Questo dovrebbe fare il trucco per te: inserisci il tag include all'interno di una sezione di blocco.

page1.html:

{% extends "base1.html" %}

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

page2.html:

{% extends "base2.html" %}

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

1
Perfetto. Per me va bene.
Trupti M Panchal

13

Maggiori informazioni sul motivo per cui non funzionava nel caso in cui aiuti le persone future:

Il motivo per cui non funzionava è che {% include%} in django non ama i caratteri speciali come l'apostrofo di fantasia. I dati del modello che stavo cercando di includere sono stati incollati da Word. Ho dovuto rimuovere manualmente tutti questi caratteri speciali e poi sono stati inclusi con successo.


3

Non è possibile inserire blocchi da un file incluso in un modello figlio per sovrascrivere i blocchi del modello principale. Tuttavia, puoi specificare un genitore in una variabile e avere il modello di base specificato nel contesto.

Dalla documentazione :

{% extends variable%} utilizza il valore di variabile. Se la variabile restituisce una stringa, Django utilizzerà quella stringa come nome del modello padre. Se la variabile restituisce un oggetto Template, Django utilizzerà quell'oggetto come template genitore.

Invece di separare "page1.html" e "page2.html", {% extends base_template %}mettili all'inizio di "commondata.html". Quindi, nella tua visualizzazione, definisci base_template"base1.html" o "base2.html".


2

Aggiunto per riferimento a persone future che lo troveranno tramite Google: potresti voler guardare il tag {% overextend%} fornito dalla libreria mezzanine per casi come questo.


1

Modifica 10 dicembre 2015 : come sottolineato nei commenti, ssi è deprecato dalla versione 1.8. Secondo la documentazione:

Questo tag è stato deprecato e verrà rimosso in Django 1.10. Utilizza invece il tag include.


A mio parere, la risposta giusta (migliore) a questa domanda è quella di podshumok , poiché spiega perché il comportamento di include quando viene utilizzato insieme all'ereditarietà.

Tuttavia, sono rimasto un po 'sorpreso dal fatto che nessuno abbia menzionato il tag ssi fornito dal sistema di template Django, che è specificamente progettato per inline includendo una parte di testo esterna . Qui, in linea mezzi il testo esterno non saranno interpretati, letti o interpolati, ma semplicemente "copiato" all'interno del modello chiamando.

Per favore, fai riferimento alla documentazione per ulteriori dettagli (assicurati di controllare la tua versione appropriata di Django nel selettore nella parte in basso a destra della pagina).

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

Dalla documentazione:

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

Attenzione anche alle implicazioni sulla sicurezza di questa tecnica e anche alla definizione ALLOWED_INCLUDE_ROOTS richiesta, che deve essere aggiunta ai file delle impostazioni.


1
Nota, a partire dalla versione 1.8, ssi è stato deprecato a favore di Include. https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#std:templatetag-include
Tim S.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.