Code

Realizzare la prima applicazione con Django, parte uno

In questo tutorial imparerai Django per esempi. Ti condurremo nella realizzazione di una semplice applicazione per sondaggi.

L'applicazione si articola in due parti:

  • un sito pubblico dove l'utente visualizza i sondaggi e vota.
  • un sito di amministrazione dove puoi aggiungere, modificare e rimuovere sondaggi.

Supporremo che Django sia già installato. Puoi verificare che ciò sia vero digitando import django dall'interprete interattivo di Python. Se il comando non produce errori Django è installato.

Creare il progetto

Se questa è la prima volta che usi Django dovrai prenderti cura di effettuare una minima configurazione iniziale. Più precisamente devi far sì che venga generato automaticamente il codice necessario per creare un progetto, inteso come una collezione di impostazioni associate ad un'istanza di Django in cui verranno precisate la informazioni relative al database, le opzioni specifiche di Django e quelle dell'applicazione.

Dalla linea di comando cambia la directory corrente posizionandoti dove memorizzerai il codice ed esegui il comando django-admin.py startproject mysite. Verrà creata la directory mysite.

(Se hai installato Django tramite python setup.py, il file django-admin.py dovrebbe trovarsi nel path di sistema. Se così non fosse lo troverai in site-packages/django/bin, dove site-packages è una directory creata in fase di installazione di Python. Considera di creare un link a questo file, ad esempio in /usr/local/bin.)

Dove mettere questo codice?

Se in passato hai avuto a che fare con PHP probabilmente sei abituato a collocare il codice delle tue applicazioni sotto la document root del Web server (ad esempio in /var/www). Con Django non devi seguire questa pratica. Non è un buon posto per memorizzare il tuo codice Python, perché come minimo rischi che qualcuno possa leggere i tuoi sorgenti sul Web, e ciò non è un vantaggio in termini di sicurezza.

Una buona scelta è di mantenere il codice al di fuori della document root, ad esempio in /home/mycode.

Vediamo che cosa è stato creato da startproject:

mysite/
    __init__.py
    manage.py
    settings.py
    urls.py

Questi file sono:

  • __init__.py: un file vuoto il cui scopo è di indicare a Python che la directory che lo contiene è da considerarsi un pacchetto Python. (Se sei alle prime armi con Python puoi trovare ulteriori informazioni sui pacchetti nella documentazione ufficiale);
  • manage.py: un'utility utilizzabile da riga di comando con cui interagire con il progetto in vari modi;
  • settings.py: contiene le impostazioni per questo progetto;
  • urls.py: è la dichiarazione degli URL per questo progetto. Consideralo come un "indice" del tuo sito realizzato con Django.

Il server di sviluppo

Verifichiamo che il nostro progetto sia funzionante. Cambia la directory corrente in mysite ed esegui il comando python manage.py runserver. Ti apparirà un output simile a:

Validating models...
0 errors found.

Django version 0.95, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

Hai avviato il server Web di sviluppo scritto in Python a corredo con Django. E' stato incluso per darti la possibilità di sviluppare rapidamente senza dover configurare subito un server di produzione come Apache, dandoti la possibilità di posticipare questo momento a quando dovrai andare in produzione.

E' una buona occasione per dirti di NON usare questo server in nessuna situazione che possa assomigliare vagamente a uno scenario di produzione. E' stato concepito unicamente per essere usato in fase di sviluppo. (In effetti il nostro impegno è orientato al campo dei framework Web, noi dei Web server).

Ora che il server è in funzione, accedi all'indirizzo http://127.0.0.1:8000/. Vedrai una pagina di benvenuto di un gradevole color blu pastello. Funziona!

Cambiare la porta

Di default, il comando runserver pone in ascolto il server di sviluppo sulla porta 8000. Se vuoi cambiare questo parametro, passa il nuovo valore dalla riga di comando. Ad esempio, se vuoi che il server resti in esecuzione sulla porta 8080:

python manage.py runserver 8080

Informazioni dettagliate sul server di sviluppo sono disponibili nella documentazione di django-admin.py.

Configurare il database

Ora modifica il file settings.py. Si tratta di un normale modulo Python contenente variabili a livello di modulo usate per la configurazione di Django. Le impostazioni sul database avvengono mediante questi parametri:

  • DATABASE_ENGINE -- 'postgresql', 'mysql' or 'sqlite3'. Ne sono previsti altri per il futuro.
  • DATABASE_NAME -- è il nome del databse o il percorso completo (assoluto) del file che contiene i dati se stai usando SQLite.
  • DATABASE_USER -- è il nome dell'utente che gestisce il database (non usato con SQLite).
  • DATABASE_PASSWORD -- è la password relativa all'utente del punto precedente (non usato con SQLite).
  • DATABASE_HOST -- è l'host su cui risiede il database. Se il database è ospitato sulla stessa macchina che fa girare Django lascia una stringa vuota (non usato con SQLite).

Note

Se stai usando PostgreSQL o MySQL assicurati di aver creato un database. In caso contrario fallo ora usando la sintassi "CREATE DATABASE database_name;" dal prompt interattivo del database in uso.

Modificando settings.py probabilmente avrai notato l'impostazione INSTALLED_APPS verso la fine del file. Questa variabile contiene i nomi di tutte le applicazioni Django attive in questa istanza di Django. Ogni applicazione può essere usata in più di un progetto, e se sei interessato puoi pacchettizzarle e distribuirle ad altre persone affinché le usino nei loro progetti.

Le applicazioni predefinite in INSTALLED_APPS sono:

  • django.contrib.auth: un sistema di autenticazione.
  • django.contrib.contenttypes: un framework per i tipi di contenuto.
  • django.contrib.sessions: un framework per le sessioni.
  • django.contrib.sites: un framework per gestire più di un sito con una sola installazione di Django.

Queste applicazioni sono incluse per convenienza e si adattano ai casi d'uso più comuni.

Ognuna di esse richiede almeno una tabella del database, quindi prima di poterne fare uso è necessario creare le tabelle necessarie. A questo scopo esiste il comando:

python manage.py syncdb

syncdb crea le tabelle necessarie alle applicazioni elencate in INSTALLED_APPS usando i parametri relativi al database che hai specificato in settings.py. Per ogni tabella che viene creata comparirà un messaggio, ed inoltre ti verrà chiesto se intendi creare un account come superutente per il sistema di autenticazione. Procedi creandolo.

Se sei interessato a sapere quali tabelle sono state create puoi usare il client interattivo a corredo con il database che stai usando e scrivere``dt`` (PostgreSQL), SHOW TABLES; (MySQL), oppure .schema (SQLite).

Per i minimalisti

Come abbiamo detto in precedenza, le applicazioni predefinite sono adeguate nei casi di utilizzo più comuni, non in tutti. Se non ti serve nessuna di queste applicazioni puoi commentare o eliminare senza problemi la riga corrispondente a ciò che non sei interessatoin INSTALLED_APPS, purché questo avvenga prima di eseguire syncdb. syncdb crea soltanto le tabelle per le applicazioni elencate in INSTALLED_APPS.

Creare i modelli

Ora l'environment lavorativo - il "progetto" - è stato configurato, sei pronto per cominciare lo sviluppo vero e proprio.

Ogni applicazione che scrivi per Django consiste in un pacchetto Python posto da qualche parte nel Python path, scritto seguendo alcune convenzioni. Django fornisce un'utility che genera automaticamente la struttura base delle directory di un'applicazione, così potrai focalizzare l'attenzione sul codice che scriverai invece che creare directory.

In questo tutorial l'applicazione verrà creata nella directory mysite, per semplicità. Come conseguenza, l'applicazione sarà vincolata al progetto, e il codice Python all'interno dell'applicazione farà riferimento a mysite.polls. Nel seguito di questo tutorial discuteremo come slegare le applicazioni per poterle distribuire.

Per creare l'applicazione assicurati di essere nella directory mysite e digita:

python manage.py startapp polls

Verrà creata una directory polls così organizzata:

polls/
    __init__.py
    models.py
    views.py

Questa struttura ospiterà l'applicazione.

Il primo passo nella scrittura di un'applicazione Web con Django consiste nel definirne i modelli, ovvero sostanzialmente lo schema del database ed alcuni metadati aggiuntivi.

Philosophy

Un modello è l'unica e definitiva sorgente di accesso ai tuoi dati. Contiene i campi essenziali e i principali comportamenti in merito ai dati che stai memorizzando. Django segue il principio DRY. L'obiettivo è quello di definire il modello dei dati in un posto ben definito ed automaticamente derivare ciò che serve esattamente da lì.

Nella nostra semplice applicazione creeremo due modelli: polls (sondaggi) e choices (scelte). Un sondaggio è caratterizzato da una domanda e da una data di pubblicazione. Una scelta invece da un testo e un contatore di voti. Ogni scelta è associata ad un sondaggio.

Questi concetti sono tradotti in semplici classi Python. Modifica il file polls/models.py in modo che il contenuto sia:

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField()

Il codice è facilmente comprensibile. Ogni modello è espresso da una sottoclasse di django.db.models.Model. Per ogni modello sono specificate alcune variabili di classe, ognuna delle quali rappresenta, all'interno del modello, un campo del database.

Ogni campo è rappresentato da un'istanza della classe models.*Field, ad esempio models.CharField per campi contenenti caratteri e models.DateTimeField per date e orari. In questo modo Django può risalire ai tipi di dato che vengono mantenuti nei diversi campi.

Il nome di ciascuna istanza models.*Field (ad esempio, question o pub_date) è il nome del campo in formato machine-readable (riconoscibile dalla macchina). Questo nome verrà usato da te per scrivere il codice Python e dal database per assegnare un nome alla colonna.

Per specificare un nome human-readable (riconoscibile dagli esseri umani) puoi dichiarare, per i vari campi, un primo argomento posizionale facoltativo. Questo valore viene usato anche in un paio di situazioni orientate all'introspezione, ed ha il vantaggio di migliorare la documentazione. Quando non è precisato un nome human-readable Django userà il nome machine-readable. In questo esempio abbiamo definito solamente un nome human-readable: in Poll.pub_date. Per tutti gli altri campi di questo modello verrà usato il nome machine-readable.

Alcune classi Field richiedono obbligatoriamente alcune informazioni aggiuntive. Ad esempio CharField richiede che venga precisata la lunghezza massima di caratteri, maxlength. Questo valore non viene usato soltanto nello schema del database, ma anche nella validazione, come vedremo tra poco.

A questo punto puoi osservare come usando models.ForeignKey viene definita una relazione. In questo modo Django viene informato che ogni scelta (Choice) è associata ad un singolo sondaggio (Poll). Django riconosce le relazioni più comunemente utilizzate: molti-a-uno, molti-a-molti, uno-a-uno.

Attivare i modelli

Il breve frammento di codice che hai appena scritto fornisce molte informazioni, che Django utilizza per:

  • creare lo schema del database (i comandi CREATE TABLE) per l'applicazione corrente;
  • creare un insieme di API Python per accedere agli oggetti Poll e Choice.

Prima che Django possa procedere però è necessario informare il progetto che l'applicazione polls è installata.

Philosophy

Le applicazioni per Django sono modulari: puoi installarle in più progetti e, poiché non risultano legate ad un particolare progetto, puoi distribuirle.

Modifica nuovamente il file settings.py e aggiungi la stringa 'mysite.polls' a INSTALLED_APPS. Questo il risultato:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'mysite.polls'
)

Ora Django è consapevole che mysite contiene l'applicazione polls e tu puoi ottenere informazioni sull'SQL con questo comando:

python manage.py sql polls

Dovrebbero comparirti le istruzioni SQL CREATE TABLE relative all'applicazione polls:

BEGIN;
CREATE TABLE "polls_poll" (
    "id" serial NOT NULL PRIMARY KEY,
    "question" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
    "choice" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
COMMIT;

Dovresti osservare che:

  • i nomi delle tabelle vengono generati automaticamente combinando il nome dell'applicazione (polls) ed il nome del modello in lettere minuscole, poll e choice. (Puoi personalizzare questa impostazione).
  • le chiavi primarie (gli ID) sono inserite automaticamente. (Puoi personalizzare anche questa impostazione).
  • come convenzione, al nome delle chiavi esterne viene accodato il suffisso "_id". Naturalmente puoi personalizzare anche questo.
  • la sintassi per la relazione di chiave esterna è coerente con il database in uso, perciò automaticamente verrà scelto auto_increment (MySQL), serial (PostgreSQL) o integer primary key (SQLite). Lo stesso principio viene adottato per quotare il nome dei campi, ad esempio, usando i doppi apici o i singoli apici. L'autore di questo documento usa PostgreSQL, perciò il risultato degli esempi è espresso con la sintassi di PostgreSQL.
  • il comando sql non esegue il codice SQL sul database, ma si limita a presentarlo a video mostrando come Django ha costruito i comandi per la creazione del database. Se ti dovesse servire potrai copiare questo output ed incollarlo dal programma client di accesso al database. Tuttavia, come vedrai tra poco Django offre un metodo molto più semplice per l'esecuzione dei comandi SQL sul database.
Questi sono altri comandi che puoi eseguire:
  • python manage.py validate polls: verifica la presenza di errori nei modelli.
  • python manage.py sqlinitialdata polls: mostra i dati iniziali richiesti per il framework di amministrazione di Django e per i tuoi modelli.
  • python manage.py sqlclear polls: mostra i comandi DROP TABLE per questa applicazione, sulla base delle tabelle già esistenti nel database (se ve ne fossero).
  • python manage.py sqlindexes polls: mostra i comandi CREATE INDEX per questa applicazione.
  • python manage.py sqlall polls: è la combinazione dei comandi 'sql', 'sqlinitialdata' e 'sqlindexes'.

L'analisi dell'output di questi comandi può aiutarti a capire che cosa succederà dietro le quinte.

Ora crea le tabelle relative ai modelli dell'applicazione eseguendo ancora una volta syncdb:

python manage.py syncdb

Il comando syncdb manda in esecuzione i comandi sql generati da 'sqlall' relativamente a tutte le applicazioni in INSTALLED_APPS che già non siano esistenti nel database. Il risultato è la creazione di tutte le tabelle, dei dati iniziali e degli indici di tutte le applicazioni che hai aggiunto al progetto dall'ultima volta che syncdb è stato lanciato. Puoi invocare syncdb tutte le volte che vuoi, e soltanto le tabelle che ancora non esistono verranno create.

Per avere informazioni complete sulle possibilità offerte dall'utility manage.py consulta la documentazione su django-admin.py.

Esperimenti con le API

Ora avvia la shell Python interattiva e fai qualche prova con l'insieme di API che Django mette a disposizione. Per invocare la shell usa questo comando:

python manage.py shell

Ti proponiamo questa sintassi invece di digitare semplicemente "python" perché usando manage.py le impostazioni di environment del progetto verrà impostato senza che tu debba fare nessuna operazione. "Impostare l'environment del progetto" coinvolge due operazioni:

  • aggiungere mysite a sys.path. Per migliorare la flessibilità, diverse parti di Django usano la notazione puntata (dotted notation) quando si riferiscono a progetti (ad esempio, 'mysite.polls.models'). Generalmente, perché questo approccio funzioni, il pacchetto mysite deve essere elencato in sys.path.
  • impostare la variabile di environment DJANGO_SETTINGS_MODULE affinché Django sia in grado di accedere al file settings.py.

Bypassare manage.py

Se non intendi usare manage.py puoi decidere di farlo senza problemi. Assicurati però che mysite sia al livello più alto del Python path (verifica che il comando import mysite non dia errori) e imposta il valore mysite.settings per la variabile DJANGO_SETTINGS_MODULE.

Per ulteriori informazioni su quanto detto consulta la documentazione su django-admin.py.

Una volta invocata la shell esplora le API relative al database:

# Importa le classi dei modelli che hai appena scritto.
>>> from mysite.polls.models import Poll, Choice

# Non esistono ancora sondaggi.
>>> Poll.objects.all()
[]

# Crea un nuovo oggetto Poll.
>>> from datetime import datetime
>>> p = Poll(question="What's up?", pub_date=datetime.now())

# Salva l'oggetto nel database. Devi invocare save() esplicitamente.
>>> p.save()

# Ora p ha un ID. Nota che il suo valore può essere "1L" invece di "1".
# Dipende dal database che stai usando. Non è nulla di preoccupante,
# significa soltanto che il backend preferisce restituire i numeri interi
# sottoforma di oggetti Python interi lunghi.
>>> p.id
1

# Accedi alle colonne del database come attributi Python.
>>> p.question
"What's up?"
>>> p.pub_date
datetime.datetime(2005, 7, 15, 12, 00, 53)

# Cambia i valori agendo sugli attributi e salvando le modifiche con
# save().
>>> p.pub_date = datetime(2005, 4, 1, 0, 0)
>>> p.save()

# objects.all() mostra tutti i sondaggi nel database.
>>> Poll.objects.all()
[<Poll: Poll object>]

Un momento. <Poll: Poll object> è una rappresentazione dell'oggetto totalmente priva di utilità. Puoi sistemare questo aggiungendo il metodo __str__() alle classi Poll e Choice contenute nel file dei modelli polls/models.py:

class Poll(models.Model):
    # ...
    def __str__(self):
        return self.question

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice

E' importante aggiungere i metodi __str__() non solo per una tua comodità durante le sessioni interattive, ma anche perché la rappresentazione testuale degli oggetti viene usata nell'interfaccia di amministrazione che Django genera in modo automatico.

Prova a farci caso, fino ad ora abbiamo usato normali metodi Python. Come controprova proviamo ad aggiungere un metodo personalizzato:

import datetime
# ...
class Poll(models.Model):
    # ...
    def was_published_today(self):
        return self.pub_date.date() == datetime.date.today()

import datetime è stato aggiunto facendo riferimento alla libreria standard di Python.

Torniamo alla shell interattiva invocando di nuovo python manage.py shell:

>>> from mysite.polls.models import Poll, Choice

# Assicurati che il metodo __str__() che hai appena aggiunto sia
# funzionante.
>>> Poll.objects.all()
[<Poll: What's up?>]

# Django mette a disposizione un ricco set di API per risalire ai dati,
# dove puoi specificare argomenti.
>>> Poll.objects.filter(id=1)
[<Poll: What's up?>]
>>> Poll.objects.filter(question__startswith='What')
[<Poll: What's up?>]

# Ottiene tutti i sondaggi dell'anno 2005. E' sottointeso che se stai
# seguendo questo tutorial in un anno diverso dal 2005 devi cambiare il
# parametro di ricerca in modo appropriato.
>>> Poll.objects.get(pub_date__year=2005)
<Poll: What's up?>

>>> Poll.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Poll matching query does not exist.

# Frequentemente ti capiterà di usare la chiave primaria per risalire ai
# dati. Per questo Django offre una scorciatoia. La seguente sintassi è
# identica a Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)
<Poll: What's up?>

# Assicurati che il metodo che hai personalizzato funzioni.
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_today()
False

# Associa qualche scelta (Choice) al sondaggio (Poll). La chiamata a create
# costruisce un nuovo oggetto di scelta, tramite una operazione di INSERT
# lo inserisce, aggiunge la scelta all'insieme delle scelte disponibili e
# restituisce un nuovo oggetto Choice.
>>> p = Poll.objects.get(pk=1)
>>> p.choice_set.create(choice='Not much', votes=0)
<Choice: Not much>
>>> p.choice_set.create(choice='The sky', votes=0)
<Choice: The sky>
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)

# Gli oggetti Choice mettono a disposizione un insieme di API per accedere
# all'oggetto Poll a cui sono associati.
>>> c.poll
<Poll: What's up?>

# Vice versa: gli oggetti Poll hanno accesso agli oggetti Choice.
>>> p.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> p.choice_set.count()
3

# Le API seguono le relazioni automaticamente sulla base delle tue
# necessità. Per separare le relazioni usa il doppio underscore. Questo
# funziona a qualsiasi livello tu voglia, non c'è limite.
# Trova tutte le scelte per qualsiasi sondaggio il cui attributo pub_date
# sia 2005.
>>> Choice.objects.filter(poll__pub_date__year=2005)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# Cancella una delle scelte. Usa delete().
>>> c.choice_set.filter(choice__startswith='Just hacking')
>>> c.delete()

Per i dettagli completi sulle API di accesso al database consulta il reference delle API di accesso al database

Quando ti accorgi di avere una certa dimestichezza con queste API leggi la seconda parte del tutarial per mettere in funzione l'interfaccia di amministrazione di Django.

Last modified 2 years ago Last modified on 01/26/12 01:12:30