Chapter 1: Introduzione
Introduzione
web2py[web2py] è un framework open source per lo sviluppo agile di applicazioni web sicure ed incentrate sui dati; è scritto ed è programmabile in Python[python]. web2py è un full-stack framework, contiene cioè tutti i componenti necessari per costruire applicazioni web pienamente funzionanti.
web2py è progettato per aiutare lo sviluppatore a seguire le corrette pratiche di ingegnerizzazione del software, come, ad esempio, l'utilizzo dello schema di sviluppo MVC (Model, View, Controller). web2py separa la fase di rappresentazione dei dati (il modello, model) dalla fase di presentazione dei dati stessi (la vista, view) a loro volta separate dalla logica e dal flusso dell'applicazione (il controllo, controller). web2py fornisce le librerie necessarie ad aiutare lo sviluppatore a progettare, implementare e testare separatamente ognuna di queste tre componenti e ad unirle infine in un'unica applicazione.
web2py è progettato per essere sicuro. Questo significa che tiene automaticamente conto di molti dei problemi che possono creare falle nella sicurezza dell'applicazione seguendo pratiche di sviluppo sicuro ben collaudate. Per esempio valida tutti gli input (per prevenire vulnerabilità di tipo injection), controlla (escaping) tutto l'output (per prevenire vulnerabilità di tipo cross-site scripting), rinomina i file caricati dagli utenti (per prevenire attacchi di tipo directory traversal). web2py lascia agli sviluppatori ben poche scelte in materia di sicurezza.
web2py include uno strato di astrazione del database (DAL, Directory Abstraction Layer) che genera codice SQL[sql-w] in modo dinamico. Lo sviluppatore non ha necessità di scrivere codice SQL, il DAL è in grado di generare SQL trasparentemente per i seguenti database: SQLite[sqlite], MySQL[mysql], PostgreSQL[postgres], MSSQL[mssql], FireBird[firebird], Oracle[oracle], IBM DB2[db2], Informix[informix], ed Ingres[ingresdb]. Il DAL inoltre è in grado di generare codice per utilizzare Google BigTable quando il framework viene eseguito nel Google App Engine (GAE) [gae]. Quando vengono definiti una o più tabelle nel database web2py genera anche una completa interfaccia web di amministrazione per accedere al database e alle tabelle.
web2py si differenzia dagli altri framework di sviluppo web in quanto è l'unico framework a sposare completamente il paradigma Web 2.0, dove il web è il computer. Infatti web2py non richiede installazione o configurazione. può essere eseguito su ogni piattaforma dove Python esiste (Windows, Windows CE, Mac OS X, iPhone e Unix/Linux) e le diverse fasi di sviluppo, installazione e manutenzione delle applicazioni possono essere eseguite localmente o remotamente tramite una interfaccia web. web2py utilizza CPython (per l'implementazione in C) o Jython (per l'implementazione in Java) nelle versioni 2.4, 2.5 e 2.6, sebbene sia 'ufficialmente' supportata solo la versione 2.5 di Python, altrimenti non potrebbe essere garantita la compatibilità con le applicazioni pre-esistenti.
web2py fornisce un sistema di gestione degli errori (ticketing). In caso avvenga un errore nell'applicazione viene emesso un ticket per l'utente e l'errore è registrato per l'amministratore.
web2py è un prodotto open source ed è rilasciato sotto la licenza GPL2.0. Le applicazioni sviluppate con web2py non sono soggette a nessun limite di licenza perchè, se non contengono codice di web2py, non sono considerate lavori derivati. web2py consente inoltre allo sviluppatore di creare versioni compilate in byte-code e di distribuirle come closed source, sebbene richiedano comunque web2py per essere eseguite. La licenza di web2py include una eccezione che permette agli sviluppatore di distribuire i loro prodotti con i binari precompilati di web2py senza il relativo codice sorgente.
Un'altra caratteristica di web2py è che noi, gli sviluppatori del framework, ci siamo impegnati a mantenere la retro-compatibilità nelle future versioni. Questo è stato fatto fin dal primo rilascio di web2py nell'ottobre del 2007. Nuove caratteristiche sono state aggiunte e i bug sono stati corretti, ma se un programma ha funzionato con la versione 1.0 di web2py quel programma funziona ancora oggi con la versione attuale.
Ecco alcuni esempi del codice utilizzato in web2py che illustrano la sua semplicità e la sua potenza. Il seguente codice:
db.define_table('person', Field('name'), Field('image', 'upload'))
crea una tabella di database chiamata "person" con due campi: "name" (di tipo stringa), ed "image" (di tipo upload, un meccanismo che consente di caricare le reali immagini). Se la tabella già esiste ma non corrisponde a questa definizione viene appropriatamente modificata.
Con la tabella appena definita il seguente codice:
form = crud.create(db.person)
crea un modulo (form) di inserimento per questa tabella che consente all'utente di caricare le immagini. Inoltre valida il form, rinomina in modo sicuro l'immagine caricata, memorizza l'immagine in un file, inserisce il relativo record nel database, previene i doppi invii, e, se la validazione dei dati inseriti dall'utente non è positiva, modifica il form aggiungendo i relativi messaggi d'errore.
Il seguente codice:
@auth.requires_permission('read','person')
def f(): ....
impedisce agli utenti di accedere alla funzione f
a meno che siano membri di un gruppo abilitato a "leggere" i record della tabella "person". Se l'utente non è autenticato viene reindirizzato alla pagina di login dell'applicazione (generata automaticamente da web2py).
Il seguente codice inserisce un componente di pagina in una vista:
{{=LOAD('other_controller','function.load',ajax=True, ajax_trap=True)}}
Questo consente a web2py di caricare in una vista il contenuto generato dalla funzione other_controller (può essere usata qualsiasi funzione). Il contenuto viene caricato tramite Ajax, viene inserito nella pagina corrente (utilizzando il layout della pagina corrente e non quello della funzione other_controller), vengono intercettate tutte le form nel contenuto caricato in modo che siano inviate tramite Ajax senza ricaricare l'intera pagina. Con questo meccanismo può essere anche caricato altro contenuto da applicazioni non web2py.
La funzione LOAD consente una programmazione estremamente modulare delle applicazioni ed è discussa in maggior dettaglio nell'ultimo capitolo di questo libro.
Principi
La programmazione in Python segue tipicamente questi principi di base:
- Non ripeterti (DRY, Don't repeat yourself).
- Deve esserci solo un modo di fare le cose.
- Esplicito è meglio che implicito.
web2py sposa completamente i primi due principi obbligando lo sviluppatore ad utilizzare chiare pratiche di ingegnerizzazione software che scoraggiano la ripetizione del codice. web2py guida lo sviluppatore nella maggior parte dei comuni compiti della fase di sviluppo di una applicazione (creazione e gestione dei form, gestione delle sessioni, dei cookie, degli errori, etc.). Per ciò che riguarda il terzo principio web2py differisce dagli altri framework di sviluppo in quanto questo principio a volte è in conflitto con gli altri due. In particolare web2py non importa l'applicazione ma la esegue in un contesto predefinito. Il contesto espone le parole chiave (keyword) di Python insieme alle keyword di web2py stesso.
Ad alcuni questo potrebbe sembrare magico, ma in realtà non dovrebbe. In pratica alcuni moduli sono già importati senza che lo sviluppatore debba esplicitamente farlo. web2py tenta di evitare la fastidiosa caratteristica di altri framework che obbligano lo sviluppatore ad importare sempre gli stessi moduli all'inizio di ogni modello e di ogni controller. Importando automaticamene questi moduli web2py fa risparmiare tempo e previene gli errori, seguendo perciò lo spirito di "Non ripeterti" e di "Deve esserci sol un modo di fare le cose".
Se lo sviluppatore desidera utilizzare altri moduli di Python o di terze parti, quei moduli devono essere importati esplicitamente, come in ogni altro programma scritto in Python.
Framework di sviluppo web
Al suo livello più basso un'applicazione web consiste di un insieme di programmi (o funzioni) che sono eseguite quando la relativa URL è visitata. L'output del programma è ciò che viene restituito al browser che a sua volta lo visualizza all'utente.
L'obiettivo di tutti i framework web è di permettere allo sviluppatore di costruire nuove applicazioni velocemente, con facilità e senza errori. Questo viene fatto tramite API e strumenti (tools) che riducono e semplificano la quantità di codice necessario.
Le due tipiche modalità di sviluppo delle applicazioni web sono:
- Generazione del codice HTML[html-w,html-o] da programma.
- Inclusione del codice all'interno delle pagine HTML.
Il primo modello è quello seguito, per esempio, dai primi script CGI (Common Gateway Interface). Il secondo modello è seguito, per esempio, da PHP[php] (dove il codice è scritto in PHP, un linguaggio simile al C), ASP (dove il codice è in Visual Basic), e JSP (dove il codice è in Java).
Ecco un esempio di un programma PHP che, quando eseguito, recupera dati da un database e ritorna una pagina HTML che mostra i relativi record:
<html><body><h1>Records</h1><?
mysql_connect(localhost,username,password);
@mysql_select_db(database) or die( "Unable to select database");
$query="SELECT * FROM contacts";
$result=mysql_query($query);
mysql_close();
$i=0;
while ($i < mysql_numrows($result)) {
$name=mysql_result($result,$i,"name");
$phone=mysql_result($result,$i,"phone");
echo "<b>$name</b><br>Phone:$phone<br /><br /><hr /><br />";
$i++;
}
?></body></html>
Il problema con questo approccio è che il codice è inserito direttamente nel codice HTML, ma lo stesso codice è utilizzato anche per generare codice HTML aggiuntivo e generare i comandi SQL di interrogazione del database. In questo modo i diversi livelli dell'applicazione si "aggrovigliano" e rendono difficile la manutenzione dell'applicazione stessa. La complessità cresce con il numero di pagine (files) che compongono l'applicazione stessa e la situazione peggiora ulteriormente per le applicazioni Ajax.
La stessa funzionalità può essere espressa in web2py con due linee di codice Python:
def index():
return HTML(BODY(H1('Records'), db().select(db.contacts.ALL)))
In questo semplice esempio, la struttura della pagina HTML è rappresentata direttamente nel codice Python dagli oggetti HTML
, BODY
, and H1
; il database db
è interrogato dal comando select
ed infine il risultato è trasformato in HTML. db
non è una keyword, ma una variabile definita dall'utente. Per evitare confusione questo nome sarà usato in questo libro per riferirsi ad una connessione al database.
I framework web sono tipicamente divisi in due categorie: framework glued che sono costruiti assemblando (incollando insieme) diverse componenti di terze parti e framework full-stack che sono costruiti creando componenti specificatamente progettati per lavorare insieme e che sono quindi strettamente integrati.
web2py è un framework full-stack. Quasi tutti i suoi componenti sono costruiti da zero e progettati per lavorare insieme, ma possono funzionare anche separamente dal framework stesso. Per esempio il DAL o il linguaggio di template possono essere usati indipendentemente dal resto del framework importando i moduli gluon.sql
o gluon.template
nelle applicazioni Python. gluon
è il nome della cartella di web2py che contiene le librerie di sistema. Alcune librerie di web2py (come quella che genera e processa i form partendo dalle tabelle del database) dipendono da altre porzioni del framework. web2py può anche utilizzare librerie Python di terze parti (per esempio altri linguaggi di template o altri DAL), ma queste non saranno strettamente integrate come i componenti originali.
Model-View-Controller
web2py utilizza il paradigma di sviluppo MVC (Model-View-Controller) che obbliga lo sviluppatore a separare la definizione dei dati (il modello, model), la presentazione dei dati (la vista, view) e il flusso delle operazioni (il controllo, controller). Considerando ancora l'esempio precedente è possibile costruire una applicazione web2py intorno ad esso.
Il tipico flusso di una richiesta in web2py è descritta nel seguente diagramma:
Nel diagramma:
- Il Server può essere il server web interno di web2py oppure un server web esterno come Apache. Il Server gestisce il multi-threading.
- "main" è la applicazione WSGI principale. Esegue tutti i compiti comuni e racchiude l'applicazione. Si occupa dei cookie, delle sessioni, delle transazioni dell'instradamento (routing) delle URL, dell'instradamento inverso (reverse routing) delle URL e del passaggio dalle URL al controller (dispatching). Può distribuire all'utente i file statici nel caso che il server web non sia configurato per farlo direttamente.
- I componenti Model, View e Controller formano l'applicazione.
- Possono esistere applicazione multiple ospitate dalla stessa istanza di web2py.
- Le linee tratteggiate rappresentano la comunicazione con il motore (o i motori) di database. Le query al database possono essere scritte direttamente in SQL (non consigliato) o utilizzando il DAL, lo strato di astrazione del database (consigliato), in modo che l'applicazione web2py non sia dipendente da uno specifico motore di database.
- Il dispatcher collega le URL richieste alle relative funzioni del controller. L'output della funzione può essere una stringa o un dizionario di simboli (una hash table). I dati nel dizionario sono visualizzati dalla vista. Se l'utente richiede una pagina HTML (questo è il comportamento di default) il dizionario è visualizzato in una pagina HTML. Se l'utente richiede la stessa pagina in XML web2py tenta di trovare una vista che possa visualizzare il dizionario in XML. Lo sviluppatore può creare delle viste per visualizzare le pagine in uno dei protocolli già supportati (HTML, XML, JSON, RSS, CSV, RTF) oppure aggiungerne altri.
- Tutte le chiamate sono racchiuse in una transazione ed ogni eccezione non gestita fa si che la transazione venga annullata. Se la richiesta è conclusa con successo la transazione viene completata.
- web2py gestisce automaticamente le sessioni e i cookie di sessione. Quando una transazione è completata la sessione è memorizzata a meno che non sia specificato diversamente.
- È possibile registrare un'operazione ricorrente in modo che sia eseguita ad orari prefissati (cron) e/o dopo il completamento di una specifica azione. In questo modo è possibile eseguire in background attività lunghe o pesanti senza rallentare la navigazione degli utenti.
Ecco una completa applicazione MVC minimale formata da soli tre file:
"db.py" è il modello:
db = DAL('sqlite://storage.sqlite')
db.define_table('contacts',
Field('name'),
Field('phone'))
Questo codice connette il database (in questo esempio è un database SQLite memorizzato nel file storage.sqlite
) e definisce una tabella chiamata contacts
. Se la tabella non esiste web2py la crea e trasparentemente genera il codice SQL nel dialetto appropriato per lo specifico motore di database utilizzato. Lo sviluppatore può vedere il codice SQL generato ma non ha la necessità di cambiare il codice se il database (di default è impostato SQLite) è sostituito con MySQL, PostgreSQL, MSSQL, FireBird, Oracle, DB2, Informix, Interbase, Ingres o BigTables nel Google App Engine.
Una volta che la tabella è stata definita e creata web2py genera inoltre una interfaccia web di amministrazione per accedere al database e alle sue tabelle chiamata appadmin.
"default.py" è il controller:
def contacts():
return dict(records=db().select(db.contacts.ALL))
In web2py le URL sono collegate ai moduli e alle chiamate alle funzioni di Python. In questo caso il controller contiene una singola funzione (o "azione") chiamata contacts
. Una azione può ritornare una stringa o un dizionario (un insieme di coppie key:value
). Se la funzione ritorna un dizionario questo è passato ad una vista (con il nome combinato del controller/azione) che lo visualizza. In questo esempio la funzione contacts
esegue una select
nel database e ritorna i record risultanti come un valore associato alla chiave records
nel dizionario.
"default/contacts.html" è la vista:
{{extend 'layout.html'}}
<h1>Records</h1>
{{for record in records:}}
{{=record.name}}: {{=record.phone}}<br />
{{pass}}
Questa vista è chiamata automaticamente da web2py dopo che la funzione associata nel controller (azione) è eseguita. Lo scopo di questa vista è visualizzare le variabili del dizionario (passato dall'azione) records=...
in HTML. La vista è scritta in HTML, ma incorpora del codice Python delimitato dai caratteri speciali {{
e }}
. Questo è diverso dall'esempio precedente in PHP perchè l'unico codice incorporato in HTML è quello dello strato di presentazione. Il file "layout.html" referenziato all'inizio della vista è incluso in web2py e costituisce il layout di base per tutte le applicazioni web2py. Il layout può essere facilmente modificato o sostituito.
Perchè web2py
web2py è uno dei molti framework di sviluppo web, ma ha caratteristiche uniche ed interessanti. web2py è stato inizialmente sviluppato come uno strumento di insegnamento, con queste fondamentali motivazioni:
- Rendere facile per gli utenti l'apprendimento dello sviluppo di applicazioni web lato server senza limitarne le funzionalità. Per questa ragione web2py non richiede nessuna installazione nè configurazione, non ha dipendenze (eccetto per la distribuzione del codice sorgente che richiede Python 2.5 e la sua libreria di moduli standard) ed espone la maggior parte delle sue funzionalità tramite un'interfaccia web.
- web2py è stabile fin dal suo primo giorno di sviluppo perchè segue una modalità di progettazione top-down: per esempio le sue API sono state progettate prima di essere state sviluppate. Ogni volta che una nuova funzionalità è stata aggiunta web2py non ha mai perso la retro-compatibilità e non perderà la retro-compatibilità quando verranno aggiunte ulteriori funzionalità in futuro.
- web2py risolve in anticipo i problemi di sicurezza più importanti (determinati da OWASP[owasp]) che affliggono molte applicazioni web moderne e che sono elencati nel successivo paragrafo.
- web2py è leggero. Le sue librerie interne, che includono il DAL, il linguaggio di template e le funzioni accessorie, occupano circa 300 KB. Tutto il codice sorgente (incluse le applicazioni di esempio e le immagini) è di circa 2 MB.
- web2py ha una impronta in memoria limitata ed è molto veloce. Utilizza il server web WSGI Rocket[rocket] progettato da Timothy Farrell. È più veloce del 30% di Apache con mod_proxy. I test indicano che, su un PC di media potenza, restituisce una pagina creata dinamicamente, senza accesso al database, in circa 10ms. L'utilizzo del DAL rallenta l'applicazione per meno del 3%.
WSGI (Web Server Gateway Interface) è uno standard emergente per la comunicazione tra i server web e le applicazioni Python.
Sicurezza
Open Web Application Security Project [owasp] (OWASP) è una comunità libera ed aperta a livello mondiale che si occupa di migliorare la sicurezza del software.
OWASP ha elencato i dieci principali problemi di sicurezza che mettono a rischio le applicazioni web. Questo elenco è qui riprodotto con una descrizione del problema e di come è affrontato in web2py:
- cross site scripting"Cross Site Scripting (XSS): una falla di tipo XSS avviene quando una applicazione prende i dati forniti dall'utente e li inoltra ad un browser senza prima validarli o codificarli. XSS consente ad un attaccante di eseguire script nel browser della vittima che possono catturare le sessioni utente, modificare siti web, introdurre virus, ed altro." web2py di default codifica (escape) tutte le variabili presentate nella vista evitando così attacchi di questo tipo.
- injection flaws"Injection Flaws: nelle applicazioni web sono comuni falle di iniezione di codice, in modo particolare di tipo SQL. L'iniezione di codice avviene quando i dati immessi dall'utente sono inviati ad un interprete come parte di un comando o di una query. I dati ostili inviati dall'attaccante fanno si che l'interprete esegua comandi non voluti o modifichi i dati." web2py include uno strato di astrazione del database (DAL) che rende impossibili le iniezioni di codice SQL. Solitamente i comandi SQL non sono scritti dallo sviluppatore ma vengono generati dinamicamente dal DAL. Questo assicura che tutti i dati siano adeguatamente codificati.
- malicious file execution"Malicious File Execution: L'esecuzione malevola di codice nei file remoti consente all'attaccante di includere codice e dati ostili, creando attacchi devastanti, che possono portare alla compromissione totale del server." web2py permette l'esecuzione unicamente delle funzioni volutamente esposte, impedendo l'esecuzione di codice malevolo. Le funzioni importate non sono mai esposte, solo le azioni dei controller sono esposte. L'interfaccia di amministrazione di web2py rende molto facile tener traccia di cosa sia esposto e cosa no.
- insecure object reference"Insecure Direct Object Reference: un riferimento diretto ad un oggetto avviene quando uno sviluppatore espone un riferimento ad un oggetto interno dell'implementazione, come un file, una cartella, un record di database o una chiave, tramite una URL o un parametro del form. L'attaccante può manipolare quei riferimenti per accedere ad altri oggetti a cui non è autorizzato." web2py non espone alcun oggetto interno; inoltre web2py valida tutte le URL in modo da prevenire attacchi di attraversamento delle cartelle (directory traversal). web2py fornisce inoltre un semplice metodo che consente di creare form che validano automaticamente tutti i valori in input.
- CSRF"Cross Site Request Forgery (CSRF): Un attacco di tipo CSRF forza il browser di un utente già autenticato a mandare una richiesta pre-autenticata ad una applicazione web vulnerabile e successivamente obbliga il browser della vittima ed eseguire una azione ostile a vantaggio dell'attaccante. CSRF può essere tanto potente quanto lo è l'applicazione che sta attaccando." web2py previene le falle di tipo CSRF così come evita il doppio invio di form assegnando un "gettone" (token) identificativo ad ogni form. Tale token è valido una sola volta. Inoltre web2py utilizza gli UUID per generare i cookie di sessione.
- information leakageimproper error handling"Information Leakage and Improper Error Handling: Le applicazioni possono rilasciare non intenzionalmente informazioni sulla loro configurazione e sul lavoro interno dell'applicazione o possono violare la privacy attraverso una varietà di problemi applicativi. Un attaccante può utilizzare queste debolezze per rubare dati sensibili o condurre attacchi di maggior gravità." web2py include un sistema di gestione delle segnalazioni d'errore (ticketing). Quando avviene un errore non viene mai visualizzato all'utente il codice sorgente che lo ha causato. L'errore, con le informazioni necessarie ad identificarlo, è registrato ed un ticket è inviato all'utente per consentire il tracciamento dell'errore. L'errore, le relative informazioni ed il codice sorgente dell'errore sono accessibili solo all'amministratore.
- "Broken Authentication and Session Management: le credenziali dell'acconto utente e i token di sessione spesso non sono protetti adeguatamente. Un attaccante può compromettere le password, le chiavi o i token di autenticazione per assumere l'identità di un altro utente." web2py fornisce un meccanismo predefinito per l'accesso dell'amministratore e gestisce le sessioni in modo indipendente per ogni applicazione. L'interfaccia amministrativa inoltre impone l'uso di cookie di sessione sicuri quando il browser non è collegato da localhost. Per le applicazioni web2py include una potente API di RBAC (Role-Based Access Control, Controllo d'accesso basato sui ruoli).
- cryptographic store"Insecure Cryptographic Storage: le applicazioni web raramente utilizzano in modo adeguato le funzioni di crittografia per proteggere i dati e le credenziali. Un attaccante può usare dati protetti debolmente per condurre un furto di identità ed altri crimini, come le frodi con la carta di credito." web2py utilizza algoritmi di cifratura di tipo MD5 o HMAC+SHA-512 per proteggere le password memorizzate. Altri algoritmi sono disponibili.
- secure communications"Insecure Communications: le applicazioni spesso non cifrano il traffico di rete quando sarebbe necessario proteggere comunicazioni sensibili." web2py include il server web ssl [ssl] Rocket WSGI, ma può anche utilizzare Apache o Lighttpd e mod_ssl per fornire una cifratura SSL delle comunicazioni.
- access restriction"Failure to Restrict URL Access: Spesso una applicazione protegge le funzioni e i dati sensibili semplicemente prevenendo la visualizzazione di link o di URL agli utenti non autorizzati. Un attaccante può usare questa debolezza pe accedere ed eseguire operazioni non autorizzate accedendo a direttamente a tali URL." web2py collega le URL di richiesta a moduli e a funzioni Python. web2py fornisce un meccanismo per indicare quali funzioni sono pubbliche e quali richiedono autenticazione ed autorizzazione. Le API di RBAC incluse consentono agli sviluppatori di restringere l'accesso al livello di ogni funzione basandosi sul login, sull'appartenenza ad un certo gruppo o sui permessi assegnati ad un gruppo. I permessi sono estremamente granulari e possono essere combinati con le funzionalitò di creazione, lettura, aggiornamento, cancellazione (CRUD, Create, read, update, delete) per consentire, per esempio, l'accesso solo ad alcune tabelle e/o record.
web2py è stato valutato dal punto di vista della sicurezza e i risultati possono essere consultati in ref [pythonsecurity].
Cosa c'è "nella scatola"
Puoi scaricare web2py direttamente dal sito ufficiale
http://www.web2py.com
web2py è composto dai seguenti componenti:
- librerie: forniscono le funzionalità di base di web2py e sono accessibili da codice.
- server web: il server web Rocket WSGI.
- l'applicazione admin: utilizzata per creare, progettare e gestire altre applicazioni web2py. admin fornisce un ambiente integrato di sviluppo (IDE, Integrated Development Environment) per costruire le applicazioni. Include inoltre altre funzionalità come i test e la riga di comando.
- l'applicazione examples: questa applicazione contiene documentazione ed esempi interattivi. examples è una copia del sito ufficiale di web2py ed include la documentazione in modo epydoc e Sphinx.
- l'applicazione welcome: questa applicazione è l'intelaiatura di base per ogni altra applicazione. Include di default un menu in CSS e l'autenticazione utente (discussa nel capitolo 8).
web2py è distribuito in codice sorgente e in forma binaria per Microsoft Windows e Mac OS X.
La distribuzione in codice sorgente può essere utilizzata in ogni piattaforma dove Python esiste e include i componenti sopra menzionati. Per eseguire il codice sorgente è necessario avere Python 2.5 installato sul sistema. È necessario inoltre aver installato uno dei motori di database supportati. Per il test e applicazioni leggere è possibile utilizzare il database SQLite, incluso con Python 2.5.
La versione binaria di web2py (per Microsoft Windows e Mac OS X) include al suo interno un interprete Python 2.5 ed il database SQLite. Tecnicamente questi non sono componenti di web2py ma l'inclusione nella distribuzione binaria consente di utilizzare web2py immediatamente.
La seguente immagine illustra la struttura complessiva di web2py:
Licenza
web2py è distribuito sotto la licenza GPL versione 2. Il testo completo della licenza è disponibile in [lgpl3].
La licenza include, ma non è limitata a, i seguenti articoli:
1. È lecito copiare e distribuire copie letterali del codice sorgente del Programma così come viene ricevuto, con qualsiasi mezzo, a condizione che venga riprodotta chiaramente su ogni copia una appropriata nota di copyright e di assenza di garanzia; che si mantengano intatti tutti i riferimenti a questa Licenza e all'assenza di ogni garanzia; che si dia a ogni altro destinatario del Programma una copia di questa Licenza insieme al Programma.
[...]
4. Non è lecito copiare, modificare, sublicenziare, o distribuire il Programma in modi diversi da quelli espressamente previsti da questa Licenza. Ogni tentativo di copiare, modificare, sublicenziare o distribuire altrimenti il Programma non è autorizzato, e farà terminare automaticamente i diritti garantiti da questa Licenza.
[...]
11. POICHÉ IL PROGRAMMA È CONCESSO IN USO GRATUITAMENTE, NON C'È GARANZIA PER IL PROGRAMMA, NEI LIMITI PERMESSI DALLE VIGENTI LEGGI. SE NON INDICATO DIVERSAMENTE PER ISCRITTO, IL DETENTORE DEL COPYRIGHT E LE ALTRE PARTI FORNISCONO IL PROGRAMMA "COSÌ COM'È", SENZA ALCUN TIPO DI GARANZIA, NÉ ESPLICITA NÉ IMPLICITA; CIÒ COMPRENDE, SENZA LIMITARSI A QUESTO, LA GARANZIA IMPLICITA DI COMMERCIABILITÀ E UTILIZZABILITÀ PER UN PARTICOLARE SCOPO. L'INTERO RISCHIO CONCERNENTE LA QUALITÀ E LE PRESTAZIONI DEL PROGRAMMA È DELL'ACQUIRENTE. SE IL PROGRAMMA DOVESSE RIVELARSI DIFETTOSO, L'ACQUIRENTE SI ASSUME IL COSTO DI OGNI MANUTENZIONE, RIPARAZIONE O CORREZIONE NECESSARIA.
12. NÈ IL DETENTORE DEL COPYRIGHT NÈ ALTRE PARTI CHE POSSONO MODIFICARE O RIDISTRIBUIRE IL PROGRAMMA COME PERMESSO IN QUESTA LICENZA SONO RESPONSABILI PER DANNI NEI CONFRONTI DELL'ACQUIRENTE, A MENO CHE QUESTO NON SIA RICHIESTO DALLE LEGGI VIGENTI O APPAIA IN UN ACCORDO SCRITTO. SONO INCLUSI DANNI GENERICI, SPECIALI O INCIDENTALI, COME PURE I DANNI CHE CONSEGUONO DALL'USO O DALL'IMPOSSIBILITÀ DI USARE IL PROGRAMMA; CIÒ COMPRENDE, SENZA LIMITARSI A QUESTO, LA PERDITA DI DATI, LA CORRUZIONE DEI DATI, LE PERDITE SOSTENUTE DALL'ACQUIRENTE O DA TERZI E L'INCAPACITÀ DEL PROGRAMMA A INTERAGIRE CON ALTRI PROGRAMMI, ANCHE SE IL DETENTORE O ALTRE PARTI SONO STATE AVVISATE DELLA POSSIBILITÀ DI QUESTI DANNI.
- web2py include codice di terze parti (per esempio l'inteprete Python, il server web Rocket e alcune librerie JavaScript). I loro rispettivi autori e licenze sono riconosciuti nel sito ufficiale di web2py[web2py] e nel codice sorgente stesso.
- Le applicazioni sviluppate con web2py, se non includono codice sorgente di web2py, non sono considerate lavori derivati. Questo significa che non sono legate alla licenza GPL V2 e possono essere distribute con qualsiasi licenza si desideri, incluse licenze closed source e commerciali.
Eccezione di Licenza Commerciale La licenza web2py include anche una eccezione commerciale: è concessa la distribuzione di una applicazione sviluppata con web2py insieme ad una versione binaria ufficiale non modificata di web2py, scaricata dal sito ufficiale[web2py], purchè sia indicato chiaramente nella licenza della applicazione quali file appartengano all'applicazione e quali appartengano a web2py.
Riconoscimenti
web2py è stato originariamente sviluppato e registrato da Massimo di Pierro. La prima versione (1.0) è stata rilasciata nell'ottobre del 2007. Da quella data web2py è stato adottato da molti utenti, alcuni dei quali hanno contribuito con report di bug, con test, debug, patch e correzioni a questo libro.
Alcuni dei principali contributori, in ordine alfabetico per nome, sono:
Alexey Nezhdanov, Alvaro Justen, Attila Csipa, Bill Ferrett, Boris Manojlovic, Brian Meredyk, Carsten Haese, Chris Clark, Chris Steel, Christopher Smiga, CJ Lazell, Craig Younkins, Daniel Lin, Denes Lengyel, Douglas Soares de Andrade, Fran Boon, Francisco Gama, Fred Yanowski, Graham Dumpleton, Gyuris Szabolcs, Hamdy Abdel-Badeea, Hans Donner, Hans Murx, Hans C. v. Stockhausen, Ian Reinhart Geiser, Jonathan Benn, Josh Goldfoot, Jose Jachuf, Keith Yang, Kyle Smith, Limodou, Marcel Leuthi, Marcello Della Longa, Mariano Reingart, Mark Larsen, Mark Moore, Markus Gritsch, Martin Hufsky, Mateusz Banach, Michael Willis, Michele Comitini, Nathan Freeze, Niall Sweeny, Niccolo Polo, Nicolas Bruxer, Ondrej Such, Pai, Phyo Arkar Lwin, Robin Bhattacharyya, Ruijun Luo (Iceberg), Sergey Podlesnyi, Sharriff Aina, Sterling Hankins, Stuart Rackham, Telman Yusupov, Thadeus Burgess, Tim Michelsen, Timothy Farrell, Yair Eshel, Yarko Tymciurak, Younghyun Jo, Zahariash.
Sono sicuro di dimenticare qualcuno, per questo chiedo scusa.
Desidero ringraziare particolarmente Jonathan, Iceberg, Nathan, and Thadeus per i loro notevoli contributi a web2py e Alvaro, Denes, Felipe, Graham, Jonathan, Hans, Kyle, Mark, Richard, Robin, Roman, Scott, Shane, Sharriff, Sterling, Stuart, Thadeus e Yarko per aver corretto vari capitoli di questo libro. Il loro contributo è stato inestimabile. Se vi sono errori in questo libro sono esclusivamente per mia colpa, introdotti probabilmente con una modifica dell'ultimo minuto. Desidero anche ringraziare Ryan Steffen della Wiley Custom Learning Solutions per l'aiuto nella pubblicazione della prima versione di questo libro.
web2py contiene codice dai seguenti autori, che desidero ringraziare: Guido van Rossum per Python[python], Peter Hunt, Richard Gordon, Timothy Farrell per il server web Rocket[rocket], Christopher Dolivet per EditArea[editarea], Bob Ippolito per simplejson[simplejson], Simon Cusack e Grant Edwards per pyRTF[pyrtf], Dalke Scientific Software per pyRSS2Gen[pyrss2gen], Mark Pilgrim per feedparser[feedparser], Trent Mick per markdown2[markdown2], Allan Saddi per fcgi.py, Evan Martin per il modulo Python memcache[memcache], John Resig per jQuery[jquery].
Il logo utilizzato sulla copertina di questo libro è stato progettato da Peter Kirchner della Young Designers.
Ringrazio Helmut Epp (Rettore della DePaul University), David Miller (Preside del College of Computing and Digital Media della DePaul University), ed Estia Eichten (Membro di MetaCryption LLC), per la loro continua fiducia ed il loro supporto.
Infine desidero ringraziare mia moglie, Claudia, e mio figlio, Marco, per avermi sopportato nelle molte ore che ho impiegato nello sviluppo di web2py, scambiando email con utenti e collaboratori e scrivendo questo libro. Questo libro è dedicato a loro.
Struttura del libro
Questo libro include i seguenti capitoli, oltre a questa introduzione:
- Il capitolo 2 è una introduzione minimalista al linguaggio Python, Richiede la conoscenza di concetti della programmazione procedurale ed orientata agli oggetti come cicli, condizioni, chiamate a funzioni e classi e copre la sintassi di base di Python. Contiene anche esempi di moduli Python che sono usati nel resto del libro. Se già conoscete Python potete saltare questo capitolo.
- Il capitolo 3 mostra come avviare web2py, discute l'interfaccia amministrativa e guida il lettore in vari esempi di complessità crescente: una applicazione che presenta una stringa, una applicazione che presenta un contatore, un blog di immagini, una applicazione completa per un wiki che permette di caricare immagini e commenti, fornisce autenticazione, autorizzazione, servizi web e un feed RSS. Nella lettura di questo capitolo si può far riferimento al capitolo 2 per la sintassi generale di Python ed ai capitoli successivi per una descrizione più dettagliata delle funzioni utilizzate.
- Il capitolo 4 copre in modo più sistematico la struttura centrale e le librerie di web2py: mapping delle URL, oggetto request, oggetto response, sessioni, cacheint, CRON, internazionalizzazione e flusso generale dell'applicazione.
- Il capitolo 5 è il riferimento per il linguaggio di template utilizzato per costruire le view. Mostra come incorporare codice Python in codice HTML e dimostra l'utilizzo delle funzioni ausiliarie (helper, che possono generare codice HTML).
- Il capitolo 6 illustra il DAL, lo strato di astrazione del database. La sintassi del DAL è presentata attraverso una serie di esempi.
- Il capitolo 7 spiega le form, la validazione delle form e la loro elaborazione. FORM è la funzione ausiliaria di basso livello per costruire le form. SQLFORM è il costruttore di form di alto livello. Nel capitolo 7 è illustrata anche la nuova API per la creazione, la lettura, l'aggiornamento e la cancellazione dei record (CRUD, Create/Read/Update/Delete).
- Il capitolo 8 descrive l'autenticazione, l'autorizzazione ed il meccanismo estendibile di controllo dell'accesso basato sui ruoli (RBAC, Role-Based Access Control) disponibile in web2py. È illustrata anche la configurazione del sistema di posta e del sistema di implementazione dei CAPTCHA poichè sono utilizzati nella fase di autenticazione. Nella terza edizione di questo libro sono stati aggiunti numerosi esempi di integrazione con meccanismi di autenticazione di terze parti, come OpenID, OAuth, Google, Facebook, Linkedin ed altri.
- Il capitolo 9 riguarda la creazione di servizi web (web services) in web2py. Sono forniti esempi di integrazione con il Web Toolkit di Google tramite Pyjamas e con Adobe Flash tramite PyAMF.
- Il capitolo 10 riguarda web2py e jQuery. web2py è progettato principalmente per la programmazione lato server, ma include jQuery, che riteniamo essere la migliore libreria open source in JavaScript disponibile per creare effetti e per Ajax. In questo capitolo è descritto come utilizzare jQuery con web2py.
- Il capitolo 11 illustra l'ambiente di produzione delle applicazioni web2py. Sono illustrati tre possibili scenari di produzione: messa in produzione su uno o più server Linux (questo è il principale ambiente di produzione), l'utilizzo come servizio in un ambiente Microsoft Windows e infine la messa in produzione sul Google Application Engine (GAE). In questo capitolo sono evidenziati anche i problemi di sicurezza e di scalabilità.
- Il capitolo 12 contiene una varietà di altre 'ricette' per risolvere specifici problemi, come gli aggiornamenti, la geolocalizzazione, la paginazione, le API per Twitter ed altro ancora.
- Il capitolo 13 è stato aggiunto nella terza edizione di questo libro e riguarda i componenti ed i plugin per web2py utilizzati per costruire applicazioni modulari. È fornito un esempio di un plugin che implementa una serie di funzionalità comuni come i grafici, il tagging, e i wiki.
Questo libro copre esclusivamente le funzionalità di base di web2py e l'API presente nel framework.
Questo libro non illustra le appliance di web2py (applicazioni già pronte). Le appliance di web2py possono essere scaricate dal relativo sito web [appliances].
Altri argomenti riguardanti web2py possono essere trovati su AlterEgo[alterego] la FAQ interattiva di web2py.
Elementi di stile
Ref.[style] contiene le buone pratiche di programmazione di Python. web2py non segue sempre queste regole non per mancanza o negligenza, siamo infatti convinti che lo sviluppatore di applicazioni web2py debba seguire queste regole (e lo incoraggiamo a farlo). Abbiamo deciso di non seguire alcune di queste regole nella definizione degli oggetti ausiliari (helper) per minimizzare la probabilità che i nomi di questi oggetti confliggano con quelli definiti dallo sviluppatore.
Per esempio la classe che rappresenta un <div>
è chiamata DIV
, mentre, secondo le regola di styte di Python dovrebbe chiamarsi Div
. Noi riteniamo che, per questo specifico caso, l'utilizzo di un nome composto di tutte lettere maiuscole sia una scelta naturale. Inoltre questo approccio lascia libertà allo sviluppatore di creare una classe chiamata "Div" se ne ha necessità. Questa sintassi inoltre si sovrappone con naturalezza alla notazione del DOM (Document Object Model, la struttura del documento HTML) utilizzata da molti browser (come ad esempio FireFox).
Secondo la guida di stile di Python i nomi composti di tutte lettere maiuscole dovrebbero essere utilizzati per le costanti e non per le variabili. Continuando con l'esempio è possibile considerare DIV
come una classe speciale che non deve mai essere modificata dallo sviluppatore perchè questo causerebbe danni alle applicazioni installate in web2py. Crediamo qundi che questo qualifichi la classe DIV
come qualcosa che dovrebbe essere trattato come una costante, giustificando maggiormente la scelta di questa notazione.
Sono utilizzate le seguenti convenzioni:
- Le funzioni ausliarie per HTML sono tutte in caratteri maiuscoli per il motivo sopra descritto (per esempio
DIV
,A
,FORM
,URL
). - L'oggetto traduttore
T
è in maiuscolo nonostante sia l'istanza di un classe e non la classe stessa. Da un punto di vista logico l'oggetto traduttore esegue un'azione simile a quelli delle funzioni ausiliarie per l'HTML: modifica la parte di visualizzazione di un oggetto. InoltreT
è facile da trovare nel codice e deve avere un nome breve. - Le classi del DAL seguono le regole di stile di Python (prima lettera maiuscola), come, per esempio,
Table
,Field
,Query
,Row
,Rows
, etc.
In tutti gli altri casi crediamo di aver seguito, per quanto sia stato possibile, la guida di stile di Python (PEP8). Per esempio tutte le istanze di oggetti sono in lettere minuscole (equest, response, session, cache) e tutte le classi interne hanno l'iniziale maiuscola.
In tutti gli esempi di questo libro le parole chiave di web2pyu sono mostrate in grassetto, mentre le stringhe e i commenti sono mostrati in corsivo.