Utente:Jennifer.394/Sandbox

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca

Jinja2 è un motore di template attrezzato per il linguaggio Python e utilizzato da framework per applicazioni web come Flask. Creato da Armin Ronacher [1] e rilasciato il 9 giugno 2008 con la versione 2.0rc1, è continuamente soggetto ad aggiornamenti ed è attualmente sotto la licenza BSD. Il progetto è indipendente e open source, supporta completamente Unicode ed è provvisto di una sandbox[2].

Jennifer.394/Sandbox
software
GenereMotore di template (non in lista)
SviluppatoreArmin Ronacher
Data prima versione9 giugno 2008
Ultima versione2.9.6 (3 Aprile 2017)
Sistema operativoMultipiattaforma
Linguaggiopython
LicenzaBSD
Sito webjinja.pocoo.org/

Introduzione[modifica | modifica wikitesto]

Jinja2 è uno dei motori di template più utilizzati con Python, è indipendente ed open source. Permette la creazione di file HTML, XML o in altri formati di markup, che vengono restituiti all’utente mediante una risposta HTTP. Le versioni di Python su cui può essere utilizzato sono la 2.4 e le successive [3]. Jinja2 non è l’unico motore di template esistente, né il primo ad essere stato creato. La sua sintassi è, al contrario, ispirata a Django, la cui nascita risale al 2003. Diversamente da Django, tuttavia, Jinja2 ha un linguaggio espressivo e fornisce un set di strumenti più potente. Tra le innovazioni ci sono la sandbox e il sistema di escape automatico. Inoltre, è interamente basato su Unicode. Jinja2 viene utilizzato da framework per applicazioni web come Flask, Bottle, Morepath e Django, e da tools come Ansible, Pelican e simili. Presenta una sintassi consistente [4] e rappresenta un passo avanti rispetto al concetto di motore di template perché da un lato si può inserire il codice all’interno dei templates, dall’altro si può sviluppare.

Caratteristiche principali[modifica | modifica wikitesto]

  • Modalità di esecuzione nella sandbox.
  • Sistema di escape HTML automatico, per prevenire attacchi cross-site scripting (XSS).
  • Ereditarietà dei template: è possibile usare uno stesso layout o uno simile per tutti i templates.
  • Alte prestazioni per la compilazione in tempo reale del codice Python.
  • Facile da debuggare.
  • Sintassi configurabile. Per esempio, può essere riconfigurato per adeguarlo ad output nei formati LaTeX o Javascript.
  • Vasta gamma di piccoli helpers utili che aiutano a risolvere compiti comuni nei templates, come la divisione di sequenze di oggetti in più colonne e altro.

Nozioni di base[modifica | modifica wikitesto]

Jinja2 ha una API molto estensiva. Utilizza le cosiddette classi loader per caricare i templates. Una volta inizializzata la classe loader, è possibile creare un' istanza della classe jinja2.Environment. Questa classe è basilare ed è usata per immagazzinare le variabili di configurazione, accedere ai templates e passare le variabili agli oggetti del template. Il modo più semplice per configurare Jinja2 e caricare templates per l’applicazione è questo:

   from jinja2 import Environment, PackageLoader, select_autoescape
   env = Environment(
         loader=PackageLoader('yourapplication', 'templates'),
         autoescape=select_autoescape(['html', 'xml'])
   ) [5]

Una volta creato l'Environment, è possibile caricare i templates e restituire l’output mediante due metodi: get_template e render. Il risultato ottenuto può essere scritto in un file. Si devono passare tutte le variabili al template, come in un dizionario: le chiavi sono i nomi delle variabili disponibili all'interno del template; i valori sono oggetti Python che si vogliono passare al template [6]. Il processo che rimpiazza le variabili con i valori attuali e restituisce la stringa di risposta, è chiamato rendering. Nella sua forma più semplice un template di Jinja2 è un file che contiene il testo di una risposta. La componente dinamica è rappresentata da una variabile racchiusa tra parentesi graffe doppie; quindi per caricare un template da un Environment dobbiamo semplicemente chiamare il metodo get_template() che poi restituisce il Template caricato, mentre per restituirlo con alcune variabili, dobbiamo chiamare il metodo render(). Il Context del template mantiene le variabili di un template, cioè immagazzina i valori passati al template e anche i nomi che il template esporta. Esso è immutabile per la stessa ragione per cui i frame locali di Python sono immutabili all’interno delle funzioni. Sia Jinja2 che Python non usano il Context/frame locali come contenitori di dati per le variabili, ma solo come risorse di dati primari.

Sandbox[modifica | modifica wikitesto]

La Sandbox di Jinja2 può essere utilizzata per valutare codici non sicuri, quindi se il template prova ad avere accesso ad un codice non sicuro interviene un SecurityError. Tuttavia, ci sono anche alcune eccezioni che non è il grado di controllare e che è compito del creatore del codice assicurarsi siano catturate.

Auto-escaping[modifica | modifica wikitesto]

L’auto-escaping è una configurazione di Jinja2 per la quale, se non esplicitamente richiesto il contrario, qualsiasi cosa venga stampata in un template viene interpretata come testo libero. Immaginiamo che il valore di una variabile x sia ciao. Se l’auto-escaping è abilitato, {{ x }} in un template produrrà la stringa esattamente come è data, cioè {{ x }}. Se invece è disabilitato, che è il default di Jinja2, il testo risultante sarà ciao. Quando si genera HTML dai templates, le variabili possono includere caratteri che influenzano l’HTML risultante. I due approcci possibili sono:

  1. L’escaping manuale di ogni variabile
  2. L’escaping automatico

Se è abilitato l’escaping manuale, è responsabilità del creatore del codice controllare le variabili, utilizzando se necessario il filtro |e :

{{ variabile|e }}

Quando invece è abilitato l’escaping automatico, questo viene applicato su tutto eccetto per i valori marcati esplicitamente come sicuri. Le variabili e le espressioni possono essere marcate come sicure o nel dizionario del Context con MarkupSafe.Markup, o nel template con il filtro |safe.

Ereditarietà di template[modifica | modifica wikitesto]

La parte più potente di Jinja è l’ereditarietà del template che permette di costruire uno scheletro di base del template contenente tutti gli elementi comuni ai vari templates e definire blocchi che i templates figli possono ereditare. Il template genitore definisce quindi un modello attraverso la costruzione di blocchi taggati con block che avvertono il motore di template della loro possibilità di essere ereditati dai templates figli. Ogni template figlio può quindi riempire tali blocchi vuoti con del contenuto e utilizza il tag {% extends %} per comunicare al motore di template che il template su cui si trova il tag estende un altro template, cioè quello genitore. Quindi Jinja2 per prima cosa, una volta incontrato extends individua il template genitore corrispondente. I blocchi possono essere annidati per layouts più complessi, ma non ci possono essere due blocchi, all’interno dello stesso template, con lo stesso nome.

API[modifica | modifica wikitesto]

  1. L’API di alto livello è l’API che si usa nell’applicazione per caricare e restituire i templates.
  2. L’API di basso livello è utile solo se si vuole scavare più a fondo in Jinja2 o sviluppare estensioni, ha funzionalità utili per capire alcuni dettagli dell’ implementazione, scopi di debugging o tecniche di estensione avanzate.
  3. L’API Meta restituisce alcune informazioni sugli alberi di sintassi astratti che possono aiutare le applicazioni ad implementare concetti di template più avanzati. Tutte le funzioni dell’API Meta operano su un albero di sintassi astratto.

Delimitatori[modifica | modifica wikitesto]

Un template in Jinja2 è un file di testo che non necessita di una estensione specifica, può generare qualsiasi testo in qualsiasi formato (HTML, XML, CSV, LaTeX, etc). Contiene variabili e/o espressioni, che possono essere rimpiazzate con dei valori al momento della resa del template, e tag che controllano la logica del template. Ci sono alcuni tipi di delimitatori, quelli di default sono:

  • {% ... %} per le istruzioni
  • {{ ... }} per le espressioni e le variabili
  • {# ... #} per i commenti [7]
  • # ... ## per istruzioni in linea

Quando c'è necessita di restituire come output caratteri che normalmente verrebbero trattati come delimitatori, è sufficiente racchiuderli tra i delimitatori utilizzati per le espressioni e le variabili:

  {{ ‘{{‘ }}

Per sezioni più grandi, ha senso racchiudere tutto in un blocco raw:

   {% raw %}
      …
   {% endraw %}

Variabili[modifica | modifica wikitesto]

Le variabili del template sono definite nel dizionario del Context passato al template e riconosciute attraverso i nomi assegnati come chiavi nel dizionario. Il costrutto {{ … }} usato nei template si riferisce ad una variabile. Questo segnaposto speciale comunica al motore di template che il valore da sostituire in quella posizione deve essere ottenuto dai dati forniti nel momento in cui il template viene reso. Jinja2 riconosce le variabili di qualsiasi tipo, anche i tipi complessi come liste, dizionari e oggetti. Le variabili possono avere attributi o elementi ai quali si può accedere. Si può usare un punto (.) per accedere agli attributi [8].

  {{ foo.bar }}

Se una variabile o un attributo non esistono, si otterrà il valore indefinito che per default restituisce una stringa vuota per le operazioni di stampa e iterazione, mentre fallisce per qualsiasi altra operazione. In Jinja2 gli identificatori validi devono concordare con l’espressione regolare [a-Za-z_] [a-z-A-Z0-9]*, cioè quella valida per Python 2.x, e i caratteri non ASCII non sono ammessi. L’espressione regolare per gli identificatori di filtri e test invece è [a-Za-z_] [a-z-A-Z0-9]*(\.[a-zA-Z_][a-zA-Z0-9_]*)* .

Filtri[modifica | modifica wikitesto]

Le variabili possono essere modificate dai filtri, separati da esse dal simbolo pipe ( | ), che possono avere opzionalmente argomenti tra parentesi. I filtri multipli possono essere concatenati e in questo caso l’output di un filtro è applicato al successivo. Gli argomenti dei filtri vengono sono racchiusi tra parentesi. Per utilizzare un filtro è sufficiente utilizzare questa struttura

   {{ variabile | filtro }}

Jinja2 ha una quantità enorme di filtri disponibili per default, tra quelli più comuni ci sono safe, capitalize, lower, upper, title, trim e striptags.

Tests[modifica | modifica wikitesto]

Accanto ai filtri, sono disponibili i “tests” . Questi possono essere utilizzare per testare una variabile in confronto ad una comune espressione. La struttura è

  {{ variabile is test }}

I tests possono accettare anche gli argomenti. Se il test ha un solo argomento non sono necessarie le parentesi.

Costrutti di controllo[modifica | modifica wikitesto]

Una struttura di controllo si riferisce a tutto ciò che controlla il flusso di un programma: istruzione if , ciclo for, macros e blocchi. Con la sintassi di default, le strutture di controllo appaiono dentro blocchi {% … %}. Queste strutture eseguono controlli sulle variabili e l’esito di tali controlli permette di restituire parti diverse del template.

Istruzione If[modifica | modifica wikitesto]

L’istruzione if in Jinja è comparabile con quella di Python. Nella forma più semplice, possiamo utilizzarla per testare se una variabile è definita, non vuota e non falsa, quindi come un controllo booleano.

{% if users %}
 <ul>
    {% for user in users %}
       <li>{{ user.username|e }}</li>
    {% endfor %}
 </ul>
 {% endif %}[9]

Per rami multipli, elif e else possono essere usati [10].

 
  {% if kenny.sick %}
     Kenny is sick.
  {% elif kenny.dead %}
     You killed Kenny!  You bastard!!!
  {% else %}
     Kenny looks okay --- so far
  {% endif %}[11]

Ciclo For[modifica | modifica wikitesto]

Cicla su ogni elemento in una sequenza. L’istruzione for può iterare su qualsiasi istanza iterabile e ha una sintassi molto semplice e vicina a Python. Permette anche l’uso, come in Python, di else, ma con un significato leggermente diverso. In Python il blocco else vien eseguito solo se non è preceduto da un comando break. Con Jinja2, il blocco else viene eseguito quando il for è vuoto.

 {% for i in [] %}
     {{ i }}
     {% else %} I’ll be printed 
  {% endfor %}
  {% for i in [‘a’] %}
     {{ i }}
     {% else %} I won’t 
  {% endfor %} [12]

Il ciclo for di Jinja2 non supporta break e continue. Per ottenere questo comportamento sono necessari dei filtri per il loop. Filtrare la sequenza durante l’iterazione consente infatti di saltare alcuni elementi:

 { for i in [1,2,3,4,5] if i >2 %}
    value: {{ i }}; loop.index: {{ loop.index }}
  {%- endfor %} [13]

Poiché le variabili nei templates conservano le proprietà dei loro oggetti, è possibile eseguire iterazioni su contenitori come i dizionari. All’interno di un blocco for, si può accedere ad alcune variabili speciali presentate nella seguente tabella[14]:

Variabile Descrizione
loop.index L'iterazione corrente del ciclo, indicizzato a 1
loop.index0 L'iterazione corrente del ciclo, indicizzato a 0
loop.revindex Il numero di iterazioni dalla fine del ciclo, indicizzato a 1
loop.revindex0 Il numero di iterazioni dalla fine del ciclo, indicizzato a 0
loop.first Restituisce vero alla prima iterazione
loop.last Restituisce vero all'ultima iterazione
loop.lenght Il numero di elementi nella sequenza
loop.cycle Una funzione helper per ciclare in una lista di sequenze
loop.depth Indica il livello di ricorsione corrente, partendo dal livello 1
loop.depth0 Indica il livello di ricorsione corrente, partendo dal livello 0

Macros[modifica | modifica wikitesto]

I Macros sono comparabili alle funzioni dei linguaggi di programmazione regolari. Sono utili per avere funzioni riutilizzabili. Jinja2 supporta anche i macro, che sono simili alle funzioni in Python e per renderli riutilizzabili possono essere immagazzinati in file da importare

  {% macro input(name, value='', type='text', size=20) -%}
       <input type="{{ type }}" name="{{ name }}" value="{{
        value|e }}" size="{{ size }}">
  {%- endmacro %}[15]

Extends, Blocks, Includes[modifica | modifica wikitesto]

Tre istruzioni utili per costruire templates da file diversi sono: block, extends e include. block ed extends lavorano sempre insieme. Il primo viene usato per definire blocchi sovrascrivibili nel template genitore, è quindi un segnaposto e un luogo di sostituzione. Il secondo richiama un template genitore con blocchi vuoti all’interno del template figlio che li eredita. Dichiara quindi che un template deriva da un altro, viene esteso perché erede di un altro. L’istruzione include permette di restituire un template all’interno di un altro. È quindi utile per includere un template e restituire i contenuti di quel file nel namespace corrente. I template inclusi hanno accesso alle variabili del Context attivo per default. Dalla versione 2.2 di Jinja è possibile marcare un include con ignore missing, in tal caso se il template da includere non esiste viene ignorato.

Estensioni[modifica | modifica wikitesto]

Le estensioni aggiungono filtri, tests e altro. Il motivo principale della creazione di estensioni è rendere una porzione di codice come fosse una classe riutilizzabile. Le estensioni vengono aggiunte all’ambiente Jinja2 al momento della creazione attraverso una lista di classi di estensioni o l’importazione. Una volta creato l’ambiente non si possono aggiungere estensioni. Non sono abilitate per default, devono essere abilitate solo quando servono.

Curiosità[modifica | modifica wikitesto]

Il nome deriva da quello di un tempio giapponese, poichè le parole temple/template hanno una pronuncia simile, mentre il numero 2 si riferisce all’ultima versione rilasciata, in continuo aggiornamento.

Filosofia[modifica | modifica wikitesto]

La logica dell' applicazione è per il controller, ma non provare a rendere troppo difficile la vita al progettista dei template fornendogli troppe poche funzionalità. [16]

Note[modifica | modifica wikitesto]

  1. ^ creatore anche di Flask
  2. ^ ambiente di esecuzione di prova integrato opzionale
  3. ^ inclusa la 3
  4. ^ consultabile all’indirizzo http://jinja.pocoo.org/
  5. ^ http://jinja.pocoo.org/docs/2.9/api/#basics
  6. ^ un template è un file che contiene il testo di una risposta, con variabili segnaposto per le parti dinamiche che saranno riconosciute solo nel contesto di una richiesta
  7. ^ non inclusi nell’output del template
  8. ^ in più allo standard Python che prevede le quadre ( [] )
  9. ^ http://jinja.pocoo.org/docs/2.9/templates/#list-of-control-structures
  10. ^ come in Python
  11. ^ http://jinja.pocoo.org/docs/2.9/templates/#list-of-control-structures
  12. ^ Italo Maia, Building web applications with Flask, 2015, Packt Publishing, Birminghampp, pp. 134-137
  13. ^ Italo Maia, Building web applications with Flask, 2015, Packt Publishing, Birminghampp, pp. 134-137
  14. ^ http://jinja.pocoo.org/docs/2.9/templates/#list-of-control-structures
  15. ^ http://jinja.pocoo.org/docs/2.9/templates/#list-of-control-structures
  16. ^ https://pypi.python.org/pypi/Jinja2/2.0

Bibliografia[modifica | modifica wikitesto]

Fonti usate per la stesura della voce:

  • Italo Maia, Building web applications with Flask, Birmingham, Packt Publishing, 2015.
  • Miguel Grinberg, Flask Web Development: Developing Web Applications with Python, USA, O'Reilly Media, Inc., 2014.
  • Rytis Sileika, Pro Python System Administration, Apress, 2014.

Voci correlate[modifica | modifica wikitesto]

Collegamenti esterni[modifica | modifica wikitesto]

[[:Categoria:Informatica]]