Scrivere pagine web a mano (codice HTML) implicherebbe tenere traccia dell'apertura e chiusura di tag. Nel caso in cui si sbagli la sintassi, non vengono sollevati messaggi di errore, semplicemente si visualizza la formattazione sbagliata.
Inoltre, violerebbero il principio DRY, principio cardine di Django.
Infine, la generazione di pagine potrebbe dover essere dinamica; ma le pagine HTML sono intrinsecamente statiche.
Nasce su questi presupposti il DTL, un'estensione del linguaggio HTML, che permette al programmatore di inserire business logic arbitraria all'interno della vista della pagina.
Linguaggio basato si blocchi anziché su tag. Mix tra linguaggio di markup e di programmazione.
I file DTL appaiono come file sorgenti statici, ma vengono elaborati dinamicamente lato server.
Il template engine di Django si occupa di parsare il template, generare un context, gestire tag, eseguire codice dinamico, per generare una pagina HTML come prodotto della "compilazione".
Il backend del template engine di un progetto Django è configurabile. Può supportare Jinga2 o DTL.
La configurazione avviene mediante settings.TEMPLATES
:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
...
}
]
Ogni applicazione gestita dal progetto può avere un proprio template.
Tra le OPTIONS
possiamo trovare la chiave context_processors
, che rappresenta i contesti a cui ha accesso il template engine.
#Rivedi
Il modulo django.template.loader
fornisce i seguenti metodi:
- get_template(template_name, name=None) -> Template
select_template(template_name_list, using=None)
come sopra ma accetta una listarender_to_string(template_name, context=None, request=None, using=None)
renderizza un template
#Attenzione in caso di errore, nota in quale metodo è stato sollevato. Eg. nell'ultimo caso il problema potrebbe risiedere nella scorretta sintassi con cui è stato scritto il template.
Noi ci interfacceremo solamente con il metodo render(...)
{{ variable.attribute }}
Il nome dell'attributo viene risolto nel seguente ordine:
- chiave di un dizionario
- attributo o un metodo
- indice numerico
Se l'attributo è un metodo chiamabile, viene chiamato senza parametri in ingresso e il valore ritornato viene sostituito allo statament.
{{ name|lower }}
{{ var|filter|another_filter }}
{{ text|truncatewords:30 }}
#Vedi reference template filters
{% for user in userbase %}
{{ user.name }} <br>
{% endfor %}
{% if %}
{{ user in admins }}
{% endif %}
<html>
<head>
...
<title> {% block head %} {% endblock %} </title>
</head>
<body> {% block body %} {% endblock %} </body>
</html>
Perché usare gli alias (campo name del path)? perché è invariante rispetto al cambio dell'endpoint. Inoltre funziona con type enforcing e path parametrizzati.
L'href
può essere ottenuto con il tag per la risoluzione {% url 'welcomepath' nome='mario' eta=25 %}
.
Come in Java e Python, esiste
super
per chiamare metodi o attributi della classe padre. A differenza di Java, può essere chiamato anche al di fuori del costruttore.
Per ottenere il contenuto di un blocco, dal padre della gerarchia, possiamo fare:
{% block content %}
{{ block.super }}
Continue content block.
{% endblock %}
Per esempio, possiamo ottenere il nome passato al path parametrico con:
{{ request.resovler_match.kwargs.nome }}
Oppure:
{{ request.GET. name }}
#Attenzione l'uso scorretto di queste sostituzioni porta spesso al template-injection, reflected XSS, etc.
#Vedi server-side template injection - SSTI. Sembra non essere un problema con un corretto rendering del template. Nell'esempio proposto non viene fatta distinzione (problema architetturale) tra template e data.
#Nota i commenti in DTL si fanno con {# tag #}