Inparando Django Framework

Introduzione

Hai mai sentito che il mondo sta diventando sempre più tecnologico e sei in qualche modo rimasto indietro? ti sei mai chiesta come creare un sito web ma non hai mai avuto abbastanza motivazione per iniziare? Hai mai pensato che il mondo del software è troppo complicato per te persino per provare a fare qualcosa per conto tuo?

Beh, abbiamo buone notizie per te! La programmazione non è così complicata come sembra e vogliamo dimostrati quanto può essere divertente.

Il tutorial non ti trasformerà magicamente in un programmatore. Se vuoi diventare bravo/a, ci vorranno mesi o addirittura anni di apprendimento e pratica. Ma ti vogliamo dimostrare che la programmazione o creare siti web non è complicato come sembra. Proveremo a spiegarti diversi argomenti come meglio possiamo, in modo che non ti senta più intimidito/a dalla tecnologia.

Speriamo di essere in grado di farti amare la tecnologia come lo facciamo noi!

Cosa imparerai durante questo tutorial?

Una volta che avrai terminato il tutorial, avrai a disposizione una semplice applicazione web: il tuo blog personale. Ti mostreremo come metterlo in linea, in modo che gli altri possano vedere il tuo lavoro!

Assomiglierà (più o meno) a questo:

Imparando Django

Informazioni e contribuzioni

Questo tutorial è mantenuto da DjangoGirls. Se trovi errori o se vuoi aggiornare questo tutorial, segui le linee guida per i collaboratori.

Installazione

Django è scritto in Python. Abbiamo bisogno di Python per fare qualsiasi cosa in Django. Iniziamo con l'installazione! Vogliamo che sul tuo pc sia installato Python 3.4 quindi se hai una versione precedente, dovrai aggiornarlo.

Windows

Puoi scaricare Python per Windows dal sito web https://www.python.org/downloads/release/python-343/. Dopo aver scaricato il file *.msi, lo dovresti eseguire (cliccaci sopra due volte) e segui le istruzioni. È importante ricordare il percorso (la directory) dove ha installato Python. Più tardi sarà necessario!

Una cosa a cui fare attenzione: sulla seconda schermata dell'installazione guidata, contrassegnata "Customize", assicurati di scorrere verso il basso e di scegliere l'opzione "Add python.exe to the Path", come illustrato qui:

Linux

È molto probabile che tu abbia Python già installato di default. Per controllare se ce l'hai già installato (e quale versione è), apri una console e digita il seguente comando:

$ python3 --version
Python 3.6.7

Se non hai Python installato o se vuoi una versione diversa, puoi installarla come segue:

Debian o Ubuntu

Digita questo comando nella tua console:

$ sudo apt install python3.6.7

openSUSE

Usa questo comando nella tua console:

$ sudo zypper install python3

OS X

Devi andare sul sito https://www.python.org/downloads/release/python-343/ e scarica il programma d'installazione di Python:

  • Scarica il file Mac OS X 64-bit/32-bit installer
  • Fai doppio click su python-3.4.3-macosx10.6.pkg per eseguire il programma d'installazione.

Verifica che l'installazione si sia conclusa correttamente aprendo l'applicazione Terminal ed eseguendo il comando python3:

$ python3 --version
Python 3.6.7

Preparare virtualenv e installare Django

Ambiente virtuale

Prima di installare Django, ti vogliamo far installare uno strumento estremamente utile per tenere in ordine l'ambiente in cui programmerai sul tuo computer. Potresti saltare questo passaggio, ma è caldamente consigliato soffermarsi. Se inizi con la migliore configurazione possibile, ti risparmierai un sacco di problemi per il futuro!

Per cui, creiamo ora un ambiente virtuale (chiamato anche un virtualenv). Virtualenv isolerà la tua configurazione di Python/Django in base ai diversi progetti. Questo significa che qualunque modifica farai su un sito non avrà alcun effetto su tutti gli altri che stai sviluppando. Chiaro ora?

Tutto quello che devi fare è trovare una cartella in cui vuoi creare il virtualenv; la tua home directory, ad esempio. Su Windows potrebbe essere C:\Users\Name (dove Name è il nome del tuo login).

Per questo tutorial useremo una nuova directory blog dalla tua home directory:

mkdir blog
cd blog

Ora creeremo un virtualenv dal nome myvenv. Questo è il formato del comando generale:

python3 -m venv myvenv

Windows

Per creare un nuovo virtualenv è necessario aprire la console (ti abbiamo spiegato come fare nei capitoli precedenti, ricordi?) ed esegui C:\Python34\python -m venv myvenv. Il risultato somiglierà a questo:

C:\Users\Name\blog> C:\Python34\python -m venv myvenv

dove C:\Python34\python è la directory in cui precedentemente hai installato Python e myvenv è il nome del tuo virtualenv. Puoi utilizzare qualsiasi altro nome, ma attieniti a utilizzare le minuscole, a non usare spazi, accenti o caratteri speciali. È meglio usare un nome breve dal momento che dovrai digitarlo spesso!

Linux e OS X

Creare un virtualenv su Linux e OS X è semplice, basta digitare: python3 -m venv myvenv. Il risultato sarà simile a questo:

~/blog$ python3 -m venv myvenv

myvenv è il nome del tuo virtualenv. Puoi usare qualsiasi altro nome, ma utilizza solo minuscole e niente spazi. Sarebbe meglio se il nome fosse corto perchè lo dovrai digitare molte volte!

Lavorare con virtualenv

Il comando sopra specificato, creerà una cartella dal nome myvenv (o col nome che hai scelto) che contiene il tuo virtual environment (ovvero un mucchio di files e cartelle).

Windows

Avvia il tuo virtualenv digitando:

C:\Users\Name\blog> myvenv\Scripts\activate

Linux e OS X

Avvia il tuo virtualenv digitando:

~/blog$ source myvenv/bin/activate

Ricordati di sostituire myvenv con il nome virtualenv che hai scelto!

Nota: a volte il comando source potrebbe non essere disponibile. In quel caso prova ad usare questo:

~/blog$ . myvenv/bin/activate

Saprai con certezza che hai avviato virtualenv quando vedrai che il prompt dei comandi nella console si presenta così:

(myvenv) C:\Users\Name\blog>

oppure:

(myvenv) ~/blog$

Fai caso al prefisso (myvenv)!

Quando si lavora all'interno di un ambiente virtuale, python farà automaticamente riferimento alla versione corretta da utilizzare. Per cui puoi digitare python invece python3.

OK, abbiamo tutte le dipendenze importanti pronte. Finalmente possiamo installare Django!

Installare Django

Ora che hai iniziato ad utilizzare il tuo virtualenv, puoi installare Django usando pip. Nella console, esegui pip install django

(myvenv) ~$ pip install django
Downloading/unpacking django
Installing collected packages: django
Successfully installed django
Cleaning up...

 

Su Windows

Se ottieni un errore quando chiami pip sulla piattaforma Windows controlla se il pathname del tuo progetto contiene spazi, accenti o caratteri speciali (i.e. C:\Users\User Name\blog). Se è così ti conviene spostarlo in un altro path senza spazi, accenti o caratteri speciali (il suggerimento è: C:\blog). Dopo averlo spostato, prova ad eseguire di nuovo il comando di cui sopra.

Installare un editor di codice

Sono disponibili diversi editor e la scelta di uno piuttosto che un altro dipende principalmente dal gusto personale. La maggior parte dei programmatori Python usa complessi ma estremamente potenti IDE (ambienti di sviluppo integrati), come PyCharm. Tuttavia, dal momento che sei ancora agli inizi non è l'editor più appropriato; quelli che ti suggeriremo noi sono ugualmente potenti ma molto più semplici da utilizzare.

I nostri suggerimenti sono riportati qui di seguito, ma sentiti libero/a di chiedere al tuo coach quali sono le sue preferenze in materia di editor, in questo modo sarà più semplice per il tuo coach aiutarti.

Gedit

Gedit è un editor open-source e gratuito, disponibile per tutti i sistemi operativi.

Scaricalo qui

Sublime Text 3

Sublime Text è uno tra gli editor più utilizzati. Ha un periodo di prova gratuito. È molto facile da installare e da utilizzare ed è disponibile per tutti i sistemi operativi.

Scaricalo qui

Atom

Atom è un nuovo editor di codice creato da GitHub. È gratuito, open-source, facile da installare e da usare. È disponibile per Windows, OSX e Linux.

Scaricalo qui

Perché installiamo un editor di codice?

Forse ti stai chiedendo per quale motivo installiamo questo editor di codice invece di usare un applicazione come Word or Blocco Note.

Il primo motivo è che il codice deve essere testo semplice, e il problema con programmi come Word e Textedit è che in realtà non producono testo semplice. Producono testo RTF (con caratteri e formattazione), utilizzando formati personalizzati come RTF (Rich Text Format).

La seconda ragione è che i code editor sono specializzati per programmare, perciò hanno molte funzionalità utili, ad esempio diversi colori per evidenziare frammenti di codice con diversi significati, o l'inserimento automatico del secondo paio di virgolette.

Vedremo tutto ciò più tardi. Il tuo fidato code editor sarà presto uno dei tuoi strumenti preferiti :)

Introduzione a Python

Scriviamo un pò codice!

La linea di comando di Python

Per iniziare a giocare con Python, devi avviare sul tuo computer una linea di comando. Dovresti già sapere come farlo -- 

Una volta pronta, segui le istruzioni riportate di seguito.

Vogliamo aprire una console Python, quindi digita python su Windows o python3 su Mac OS/Linux e premi invio.

$ python3
Python 3.4.3 (...)
Type "help", "copyright", "credits" or "license" for more information.
>>>

Il tuo primo comando Python!

Dopo aver eseguito il comando Python, il prompt è cambiato in >>>. Significa che per ora dovremmo utilizzare comandi nel linguaggio Python. Non devi digitare >>> - Python lo farà per te.

Se ad un certo punto vuoi uscire dalla console di Python, digita exit() oppure usa la scorciatoia Ctrl + Z per Windows e Ctrl + D per Mac/Linux. Allora non vedrai più >>>.

Per ora non vogliamo uscire dalla console Python. Vogliamo saperne di più. Cominciamo con qualcosa davvero semplice. Per esempio, prova un po' di matematica, come 2 + 3 e premi invio.

>>> 2 + 3
5

Fantastico! Hai visto come è comparsa la risposta? Python conosce la matematica! potresti provare altri comandi come: - 4 * 5 - 5 - 1 - 40 / 2

Divertiti con questo per un pò e dopo torna qui :).

Come puoi vedere, Python è una buona calcolatrice. Ora ti starai sicuramente chiedendo cos'altro è capace di fare...

Stringhe

Che ne dici di scrivere il tuo nome? Digitalo tra virgolette così:

>>> "Ola"
'Ola'

Hai appena creato la tua prima stringa! Una stringa è una sequenza di caratteri che possono essere elaborati da un computer. La stringa deve sempre iniziare e finire con lo stesso carattere. Che può essere una virgoletta semplice (') o doppia (") (non c'è differenza!) Le virgolette dicono a Python che il contenuto al loro interno è una stringa.

Le stringhe possono essere legate assieme. Prova questo:

>>> " Ciao " + "Ola"
'Ciao Ola'

Puoi anche moltiplicare le stringhe con un numero:

>>> "Ola" * 3
'OlaOlaOla'

Se devi mettere un apostrofo nella tua stringa, hai due modi per farlo.

Utilizzando le virgolette doppie:

>>> "Correre verso l'albero"
"Correre verso l'albero"

Bello, eh? Per vedere il tuo nome in maiuscolo, digita:

>>> "Ola".upper()
'OLA'

Hai appena usato la funzione upper sulla tua stringa! Una funzione (come upper()) è una sequenza di istruzioni che Python deve eseguire su un determinato oggetto ("Ola").

Se vuoi sapere il numero delle lettere presenti nel tuo nome, c'è una funzione anche per quello!

>>> len("Ola")
3

Ti stai chiedendo perché certe volte chiami una funzione con un . alla fine di una stringa (come "Ola".upper()) ed in altri casi chiami prima una funzione e poi metti la stringa tra parentesi? Beh, in alcuni casi, le funzioni appartengono ad oggetti, come upper(), che può essere eseguita solo su stringhe. In questo caso, chiamiamo la funzione metodo. Altre volte, le funzioni non appartengono a niente di specifico e possono essere utilizzate su diversi tipi di oggetti, proprio come len(). Ecco perché stiamo dando "Ola" come un parametro alla funzione len.

Indice

OK, basta con le stringhe. Ecco fino ad ora quanto hai imparato:

  • il prompt - digitare i comandi (codice) nel prompt di Python restituisce risposte in Python
  • numeri e stringhe - in Python i numeri vengono utilizzati per la matematica e le stringhe per oggetti testuali
  • operatori - come + e *, combinano i valori per produrne di nuovi
  • funzioni - come upper() e len(), eseguono azioni su oggetti.

Queste sono le basi di ogni linguaggio di programmazione che impari. Pronta per qualcosa di più complicato? Scommetto che lo sei!

Errori

Proviamo qualcosa di nuovo. Possiamo ottenere la lunghezza di un numero nella stessa forma in cui abbiamo potuto scoprire la lunghezza del nostro nome? Digita len(304023) e premi Invio:

>>> len(304023)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()

Abbiamo ottenuto il nostro primo errore! Ci dice che gli oggetti di tipo "int" (integers, numeri interi) non hanno lunghezza. Quindi cosa possiamo fare? Forse possiamo scrivere il nostro numero come una stringa? Le stringhe hanno una lunghezza, vero?

>>> len(str(304023))
6

Ha funzionato! Usiamo la funzione str all'interno della funzione lenstr() converte tutto in stringhe.

  • La funzione str converte le cose in stringhe
  • La funzione int converte le cose in numeri interi

Importante: possiamo convertire i numeri in testo, ma non possiamo convertire il testo in numeri - cosa potrebbe essere int('hello')?

 

Variabili

Un concetto importante nella programmazione è quello delle variabili. Una variabile è un nome per un qualcosa che deve essere utilizzato sucessivamente. I programmatori usano queste variabili per archiviare dati, rendere il loro codice più leggibile e per non dover tenere a mente cosa sono queste cose.

Diciamo che vogliamo creare una nuova variabile chiamata nome:

>>> nome = "Ola"

Vedi? È facile! è semplicemente: nome è uguale a Ola.

Come avrai notato, il programma non ha ritornato nulla, diversamente da prima. Quindi come facciamo a sapere che la variabile esiste? Digita nome e premi enter:

>>> nome
'Ola'

Evvai! La tua prima variabile :)! Puoi sempre modificare a cosa si riferisce:

>>> nome = "Sonja"
>>> nome
'Sonja'

La puoi utilizzare anche nelle funzioni:

>>> len(nome)
5

Fantastico, vero? Certo, le variabile possono essere qualsiasi cosa, così come i numeri! Prova questo:

>>> a = 4
>>> b = 6
>>> a * b
24

Ma cosa succede se utilizziamo il nome sbagliato? Riesci a immaginare cosa succederebbe? Proviamo!

>>> city = "Tokyo"
>>> ctiy
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'ctiy' is not defined

Un errore! Come puoi vedere, Python ha diversi tipi di errori e questo qui si chiama NameError. Python ti darà questo errore se provi ad utilizzare una variabile che non è stata ancora definita. Se incontri questo errore più tardi, controlla il tuo codice per vedere se hai digitato in modo errato i nomi.

Giocaci per un po' e vedi cosa puoi fare!

La funzione print

Prova questo:

>>> nome = 'Maria'
>>> nome
'Maria'
>>> print(nome)
Maria

Quando digiti nome, l'interprete di Python risponde con una stringa rappresentazione della variabile 'nome', che contiene le lettere M-a-r-i-a, circondate da singole virgolette, ''. Quando dici print(nome), Python "stamperà" i contenuti della variabile sullo schermo, senza le virgolette, che è più pulito.

Come vedremo dopo, print() è anche utile quando vogliamo stampare le cose dall'interno delle funzioni, oppure quando vogliamo stampare le cose in molteplici righe.

Liste

Oltre alle stringhe ed ai numeri interi, Python ha tanti tipi di oggetti. Ora ne introdurremo uno chiamato lista. Le liste sono fatte proprio come immagini: sono oggetti che sono liste di altri oggetti :)

Vai avanti e crea una lista:

>>> []
[]

Si, questa lista è vuota. Non serve a molto, giusto? Creiamo una lista di numeri della lotteria. Non vogliamo ripetere tutto ogni volta, quindi metteremo la lista in una variabile:

>>> lotteria = [3, 42, 12, 19, 30, 59]

Abbiamo una lista! Cosa possiamo farne? Vediamo quanti numeri della lotteria ci sono nella lista. Hai idea di quale funzione potresti utilizzare per farlo? Lo abbiamo imparato insieme prima!

>>> len(lotteria)
6

Si! len() può darti il numero di oggetti in una lista. Utile, vero? Forse abbiamo risolto:

>>> lotteria.sort()

Questo comando non dà nessun risultato, ha semplicemente cambiato l'ordine in cui i numeri appaiono nella lista. Stampiamo di nuovo la lista per vedere cosa è successo:

>>> print(lotteria)
[3, 12, 19, 30, 42, 59]

Come puoi vedere, adesso i numeri nella tua lista sono ordinati dal valore più basso a quello più alto. Congratulazioni!

Vogliamo invertire quell'ordine? Facciamolo!

>>> lotteria.reverse()
>>> print(lotteria)
[59, 42, 30, 19, 12, 3]

Facile, vero? Se vuoi aggiungere qualcosa alla tua lista, puoi farlo digitando questo comando:

>>> lotteria.append(199)
>>> print(lotteria)
[59, 42, 30, 19, 12, 3, 199]

Se vuoi mostrare solo il primo numero, puoi farlo usando gli indici. L'indice è il numero che dice la posizione esatta dell'elemento all'interno di una lista. I programmatori preferiscono iniziare a contare da 0, quindi il primo oggetto nella lista è all'indice 0, il successivo all'1, e così via. Prova questo:

>>> print(lotteria[0])
59
>>> print(lotteria[1])
42

Come puoi vedere, puoi accedere a diversi oggetti nella tua lista usando il nome della lista e l'indice dell'oggetto all'interno delle parentesi quadre.

Per eliminare qualcosa dalla lista dovrai usare indexes come abbiamo visto sopra, e lo statement pop(). Proviamo a fare qualcosa per rafforzare quanto imparato prima; elimineremo il primo numero della lista.

>>> print(lotteria)
[59, 42, 30, 19, 12, 3, 199]
>>> print(lotteria[0])
59
>>> lotteria.pop(0)
>>> print(lotteria)
[42, 30, 19, 12, 3, 199]

Ha funzionato a meraviglia!

Prova altri indici: 6, 7, 1000, -1, -6 o -1000. Prova a prevedere il risultato ancora prima di eseguire il comando. Hanno senso i risultati?

Per saperne di più su i metodi disponibili per le liste puoi consultare questo capitolo della documentazione Python: https://docs.python.org/3/tutorial/datastructures.html

Dizionari

Un dizionario (dictionary) è simile a una lista, ma accedi ai valori cercando una chiave invece di un indice. Una chiave può essere qualsiasi stringa o numero. La sintassi per definire un dizionario vuoto è:

Ora, prova a scrivere il seguente comando (prova a sostituirlo con le tue informazioni):

>>> partecipante = {'nome': 'Ola', 'paese': 'Polonia', 'numeri_preferiti': [7, 42, 92]}

Con questo comando hai appena creato una variabile chiamata partecipante con tre coppie di chiavi-valori:

  • La chiave nome va a indicare il valore 'Ola' (un oggetto stringa),
  • paese indica 'Polonia' (un'altra stringa),
  • e numeri_preferiti indica [7, 42, 92] (una lista con tre numeri al suo interno).

Puoi controllare il contenuto di chiavi individuali con questa sintassi:

>>> print(partecipante['nome'])
Ola

Vedi, assomiglia ad una lista. Ma non devi ricordare l'indice - solo il nome.

Cosa succede se chiediamo a Python il valore di una chiave che non esiste? Riesci a indovinarlo? Proviamo!

>>> partecipante['età']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'età'

Guarda, un altro errore! Questo qua è un KeyError. Python è utile e ti dice che la chiave 'età' non esiste in questo dizionario.

Quando usare un dizionario o una lista? Bella domanda. Prova a formulare una soluzione mentalmente prima di vedere la risposta nella prossima riga.

  • Ha bisogno di una sequenza ordinata di elementi? Fai una lista.
  • Hai bisogno di associare i valori alle chiavi, così che potrai cercarle agilmente (per chiave) dopo? Usa un dizionario.

I dizionari, come le liste, sono mutable, significa che possono essere cambiati dopo che sono stati creati. Si possono aggiugere nuove coppie chiave/valore ad un dizionario dopo averlo creato:

>>> partecipante['linguaggio_preferito'] = 'Python'

Così come succede se applicato alle liste, il metodo len() restituisce il numero di coppie chiave/valore anche quando applicato a un dizionario. Vai e digita il comando:

>>> len(partecipante)
4

Spero che abbia senso per te. :) Pronta per divertirti con i dizionari? Vai alla prossima riga per realizzare altre cose fantastiche.

Puoi usare il comando pop() per cancellare un elemento nella directory. Se vuoi cancellare la voce che corrisponde alla chiave 'numeri_preferiti', digita il seguente comando:

>>> partecipante.pop('numeri_preferiti')
>>> partecipante
{'paese': 'Polonia', 'linguaggio_preferito': 'Python', 'nome': 'Ola'}

Come puoi vedere dall'output, la coppia chiave-valore corrispondente alla chiave 'numeri_preferiti' è stato cancellata.

Puoi anche cambiare un valore associato ad una chiave già creata nel dizionario. Digita:

>>> partecipante['paese'] = 'Germania'
>>> partecipante
{'paese': 'Germania', 'linguaggio_preferito': 'Python', 'nome': 'Ola'}

Come puoi vedere, il valore della chiave 'paese' è stato cambiato da 'Polonia' a 'Germania'. :) Eccitante, vero? Evviva! Hai già imparato un'altra cosa fantastica.

Indice

Fantastico! ora sai molto sulla programmazione. In questa ultima parte hai imparato:

  • errori - ora sai come leggere e capire gli errori che appaiono se Python non comprende un comando che gli hai dato
  • variabili - nomi per oggetti. Ti permettono di scrivere codice più semplice e di renderlo più leggibile
  • liste - liste di oggetti archiviati in un ordine particolare
  • dizionari - oggetti archiviati come coppie di chiave-valore

Sei emozionato/a per la prossima parte? :)

Confrontare le cose

Larga parte della programmazione include il confrontare le cose. Qual è la cosa più semplice da confrontare? I numeri, senza dubbio. Vediamo come funziona:

>>> 5 > 2
True
>>> 3 < 1
False
>>> 5 > 2 * 2
True
>>> 1 == 1
True
>>> 5 != 2
True

Abbiamo dato a Python alcuni numeri da mettere a confronto. Come puoi vedere, Python può mettere a confronto non solo numeri, ma anche i risultati dei metodi. Forte, eh?

Ti sei chiesta perché abbiamo messo due simboli di uguale == uno vicino all'altro per confrontare i numeri? Usiamo un singolo = per assegnare valori alle variabili. Sempre, sempre devi mettere due == se vuoi controllare se le cose sono uguali. Possiamo affermare anche che le cose sono diverse tra di loro. Per dirlo, usiamo il simbolo !=, come mostrato nell'esempio sopra.

Dai a Python altri due compiti:

>>> 6 >= 12 / 2
True
>>> 3 <= 2
False

> e < sono facili, ma cosa significano >= e <=? Leggili così:

  • x > y significa: x è maggiore di y
  • x < y significa: x è minore di y
  • x <= y significa: x è minore o uguale a y
  • x >= y significa: x è maggiore o uguale a y

Fantastico! Vuoi farne due o tre? prova questo:

>>> 6 > 2 and 2 < 3
True
>>> 3 > 2 and 2 < 1
False
>>> 3 > 2 or 2 < 1
True

Puoi dare a Python tutti i numeri da confrontare che vuoi, ti darà sempre una risposta! Molto intelligente, vero?

  • and - se usi l'operatore e, entrambe le cose confrontate devono essere True in modo tale che l'intero comando sia True
  • or - se usi l'operatore o, solo una delle cose messe a confronto deve essere True in modo tale che l'intero comando sia True

Hai sentito parlare dell'espressione "comparare mele e arance"? Proviamo l'equivalente in Python:

>>> 1 > 'django'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'int' and 'str'

Dall'espressione puoi capire che Python non è in grado di mettere a confronto un numero (int) e una stringa (str). Ci mostra invece un TypeError e ci dice che i due tipi non possono essere messi a confronto.

Booleano

Accidentalmente, hai appena imparato un nuovo tipo di oggetto in Python. Si chiama Boolean e probabilmente è il tipo più facile che ci sia.

Ci sono solo due oggetti Boolean:

  • True
  • False

Ma perché Python possa capirlo, bisogna sempre scrivere True (prima lettera maiuscola, le altre minuscole). true, TRUE, tRUE non funzionano -- solo True è corretto. (Lo stesso vale per False, ovviamente.)

I Boolean possono anche essere variabili! Guarda qui:

>>> a = True
>>> a
True

Lo puoi fare anche in questa forma:

>>> a = 2 > 5
>>> a
False

Fai pratica e divertiti con i Boolean provando ad eseguire i seguenti comandi:

  • True and True
  • False and True
  • True or 1 == 1
  • 1 != 2

Congratulazioni! I valori Boolean sono tra le cose più interessanti della programmazione e tu hai appena imparato ad utilizzarli!

Salvalo!

Finora abbiamo scritto il codice python nell'interprete, che ci permette di inserire una linea di codice per volta. I programmi vengono salvati in file ed eseguiti dall'interpreter del nostro linguaggio di programmazione o dal compiler. Fino ad ora abbiamo eseguito i nostri programmi una riga per volta nell' interprete di Python. Avremo bisogno di più di una riga di codice per i prossimi compiti, quindi dovremo fare queste cose velocemente:

  • Uscire dall'interprete di Python
  • Aprire l'editor di codice che abbiamo scelto
  • Salvare un po' di codice in un file python
  • Eseguirlo!

Per uscire dall'interprete di Python che è quello che stavamo utilizzando, digita la funzione exit() :

>>> exit()
$

Questo ti immetterà nel prompt dei comandi.

Prima, abbiamo preso un editore di codice dalla sezione code editor. Dovremo aprire l'editor ora e scrivere un po' di codice in un nuovo file:

print('Ciao, Django girls!')

Nota Dovresti notare una delle cose più belle degli editori di codice: i colori! Nella console Python ogni cosa era dello stesso colore, mentre ora dovresti visualizzare la funzione print di un colore differente rispetto alla stringa che la segue. Questa viene chiamata "sintassi evidenziata", ed è veramente utile quando si scrive codice. Il colore serve come suggerimento, ad esempio per una stringa che non è chiusa, o un errore di digitazione di una keyword (come la def per le funzioni, che vedremo più avanti). Questo è uno dei motivi per cui usiamo un editor di codice :)

Ovviamente a questo punto sei una programmatrice Python senior, quindi sentiti libera di scrivere un po' del codice che hai imparato oggi.

Ora dobbiamo salvare il file e dargli un nome descrittivo. Chiama il file python_intro.py e salvalo sulla tua scrivania. Puoi chiamare il file come vuoi, ma è importante assicurarsi che finisca con .py. L'estensione .py dice al Sistema Operativo che questo è un file eseguibile python e che Python può eseguirlo.

&#xC8; ora di eseguire il file! Usando le nozioni che hai imparato nella sezione command line, usa il terminal per cambiare cartella alla scrivania.

Su un Mac, il comando assomiglierà a questo:

$ cd ~/Desktop

Su Linux, sar&#xE0; come questo (la parola "Desktop" potrebbe essere tradotta nella tua lingua):

$ cd ~/Desktop

E su windows, sara come questo:

> cd %HomePath%\Desktop

Se rimani bloccata, chiedi aiuto.

Ora usa Python per eseguire il codice nel file:

$ python3 python_intro.py
Ciao, Django girls!

Perfetto! Hai appena eseguito il tuo primo programma Python salvato su un file. Grande, no?

Ora puoi continuare con uno strumento essenziale nella programmazione:

If...elif...else

Molte cose dovrebbero essere eseguite soltanto quando si incontrano certe condizioni. È per questo che Python ha gli if statements.

Sostituisci il codice nel file python_intro.py con questo:

if 3 > 2:

Se salviamo questo codice e lo eseguiamo, incontriamo un errore come questo:

$ python3 python_intro.py
File "python_intro.py", line 2
         ^
SyntaxError: unexpected EOF while parsing

Python si aspetta che gli vengano fornite ulteriori istruzioni che saranno eseguite se la condizione 3 > 2 risulterà vera (o True se vogliamo). Proviamo a fare in modo che Python stampi "Funziona!". Modifica il tuo codice nel tuo file python_intro.py con questo:

if 3 > 2:
     print('Funziona!')

Vedi come abbiamo indentato la riga successiva usando 4 spazi? Si deve fare così in modo tale che Python sappia quale codice eseguire se il risultato è True. Puoi fare uno spazio, ma circa tutti i programmatori di Python ne fanno 4 per far vedere le cose più ordinate. Anche un signolo tab conta come 4 spazi.

Salvalo ed eseguilo di nuovo:

$ python3 python_intro.py
Funziona!

E se una condizione non è Vera?

In esempi precedenti, il codice è stato eseguito solo quando le condizioni erano True. Ma Python ha anche gli elif e else statements:

if 5 > 2:
     print('5 &#xE8; infatti maggiore di 2') 
else:
     print('5 non &#xE8; maggiore di 2')

Quando viene lanciato, mostrer&#xE0;:

$ python3 python_intro.py
5 &#xE8; infatti maggiore di 2

Se 2 fosse un numero maggiore di 5, allora andrebbe in esecuzione il secondo comando. Facile, vero? Andiamo a vedere come funziona elif:

nome = 'Sonja'
if nome == 'Ola':
    print('Ciao Ola!')
elif nome == 'Sonja':
    print('Ciao Sonja!')
else:
    print('Ciao anonimo!')

ed eseguito:

$ python3 python_intro.py
Ciao Sonja!

Hai visto cosa &#xE8; successo? elif ti consente di aggiungere condizioni supplementari che verranno eseguite se nessuna delle condizioni precedenti viene soddisfatta.

Allo statement iniziale if puoi far seguire tutti gli statement elif che vuoi. Per esempio:

volume = 57
if volume < 20:
    print("Piuttosto basso.")
elif 20 <= volume < 40:
    print("Adatto per musica di sottofondo")
elif 40 <= volume < 60:
    print("Perfetto, posso apprezzare ogni dettaglio")
elif 60 <= volume < 80:
    print("Ideale per le feste")
elif 80 <= volume < 100:
    print("Un po' altino!")
else:
    print("Oddio, le mie orecchie! :(")

Python esegue ogni singolo test in sequenza e scrive:

$ python3 python_intro.py
Perfetto, posso apprezzare ogni dettaglio

Indice

Nei tre esercizi precedenti hai imparato:

  • come confrontare le cose - in Python puoi mettere a confronto le cose usando >>===<=< e gli operatori eo
  • Boolean - una tipologia di oggetto che può avere solo uno di questi due valori: True o False
  • come Salvare file - archiviare codice nei file in modo da poter eseguire programmi più lunghi.
  • if...elif...else - affermazioni che ti permettono di eseguire codice solo quando vengono incontrate certe condizioni.

È ora dell'ultima parte del capitolo!

Le funzioni personalizzate!

Ti ricordi quelle funzioni che puoi eseguire in Python come len()? Beh, buone notizie, ora imparerai a scrivere delle funzioni tutte tue!

È stato facile! Costruiamo la nostra prima funzione con parametri. Useremo l'esempio precedente - una funzione che dice 'ciao' alla persona che lo esegue - aggiungendo il nome:

def ciao():
    print('Ciao!')
    print('Come stai?')

ciao()

Okay, la nostra prima funzione &#xE8; pronta!

Ti starai chiedendo perch&#xE9; abbiamo scritto il nome della funzione alla fine del file. Perch&#xE9; Python legge il file e lo esegue dall'alto verso il basso. Quindi per poter utilizzare la nostra funzione, dobbiamo riscriverla alla fine.

Eseguiamolo e vediamo cosa succede:

$ python3 python_intro.py
Ciao!
Come stai?

&#xC8; stato facile! Costruiamo la nostra prima funzione con parametri. Useremo l'esempio precedente - una funzione che dice 'ciao' alla persona che lo esegue - aggiungendo il nome:

def ciao(nome):

Come puoi vedere, abbiamo dato alla nostra funzione un parametro chiamato nome:

def ciao(nome):
    if nome == 'Ola':
        print('Ciao Ola!')
    elif nome == 'Sonja':
        print('Ciao Sonja!')
    else:
        print('Ciao anonimo!')

ciao()

Ricorda: La funzione print è rientrata di 4 spazi rispetto allo statement if. Infatti, la funzione viene eseguita quando la condizione viene soddisfatta. Vediamo ora come funziona:

$ python3 python_intro.py
Traceback (most recent call last):
File "python_intro.py", line 10, in <module>
  ciao()
TypeError: ciao() missing 1 required positional argument: 'nome'

Ops, un errore. Fortunatamente, Python ci fornisce un messaggio di errore che ci può servire. Ci dice che la funzione ciao() (quella che abbiamo definito) ha un argomento richiesto (chiamato nome) e che ci siamo dimenticati di metterlo quando abbiamo chiamato la funzione. Sistemiamolo alla fine del file:

ciao("Ola")

Ed eseguiamo di nuovo:

$ python3 python_intro.py
Ciao Ola!

E se cambiamo il nome?

ciao("Sonja")

Ed eseguilo:

$ python3 python_intro.py
Ciao Sonja!

Ora, cosa pensi che succederà se scrivi un altro nome? (non Ola o Sonja) Provaci e vedi se la tua ipotesi è giusta. Dovrebbe stampare questo:

Ciao anonimo!

Fantastico, vero? In questo modo non devi ripetere tutto ogni volta che vuoi modificare il nome della persona che la funzione dovrebbe salutare. Ed è esattamente per questo che abbiamo bisogno delle funzioni - non vuoi ripetere il tuo codice!

Facciamo una cosa più intelligente -- ci sono più di due nomi, e scrivere una condizione per ognuno sarebbe complicato, vero?

def ciao(nome):
    print('Ciao ' + nome + '!')

ciao("Rachel")

Ora chiamiamo il codice:

$ python3 python_intro.py
Ciao Rachel!

Congratulazioni! Hai appena imparato a scrivere delle funzioni :)

Loop

È l'ultima parte. Abbiamo fatto in fretta, vero? :)

I programmatori non amano ripetere ciò che scrivono. La programmazione mira a automatizzare le cose, non vorremo mica salutare ognuno col suo nome manualmente? Ecco un caso in cui i loop ci tornano comodi.

Ti ricordi ancora delle liste? Facciamo una lista di ragazze:

ragazze = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Tu']

Vogliamo salutare tutte loro per nome. Abbiamo la funzione ciao per farlo, quindi usiamola in loop:

for nome in ragazze:

Lo statement for si comporta in modo simile allo statement if; il codice sottostante deve essere rientrato di quattro spazi.

Qua c'&#xE8; l'intero codice che sar&#xE0; nel file:

def ciao(nome):
    print('Ciao ' + nome + '!') 

ragazze = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Tu']
for nome in ragazze:
    ciao(nome)
    print('Prossima ragazza')

E quando lo eseguiamo:

$ python3 python_intro.py
Ciao Rachel!
Prossima ragazza
Ciao Monica!
Prossima ragazza
Ciao Phoebe!
Prossima ragazza
Ciao Ola!
Prossima ragazza
Ciao You!
Prossima ragazza

Come puoi vedere, tutto quello che metti all'interno di un for statement con una spaziatura si ripeter&#xE0; per ogni elemento della lista girls.

Puoi anche utilizzare for su numeri usando la funzione range:

for i in range(1, 6):
    print(i)

Che stamperà:

1
2
3
4
5

range è una funzione che crea una lista di numeri che si seguono uno dopo l'altro (questi numeri vengono forniti da te come parametri).

Nota che il secondo di questi due numeri non è incluso nella lista prodotta da Python ( ciò significa che range(1, 6) conta da 1 a 5, ma non include il numero 6). Questo perché "range" è mezzo-aperto e con ciò intendiamo che include il primo valore, man non l'ultimo.

Indice

È tutto. Sei grande! Questo capitolo non era affatto facile, puoi essere orgogliosa di te stessa. Noi siamo fierissimi di te per avercela fatta fino a qui!

Potresti desiderare di fare brevemente qualcos'altro - stiracchiati, fai due passi, riposa gli occhi - prima di continuare con il prossimo capitolo. :)

Che cos'è Django?

Django (/ˈdʒæŋɡoʊ/ jang-goh) è un framework per applicazioni web gratuito e open source, scritto in Python. Un web framework è un insieme di componenti che ti aiuta a sviluppare siti web più velocemente e facilmente.

Quando si costruisce un sito web, si ha sempre bisogno di un insieme di componenti simili: un sistema per gestire l'autenticazione dell'utente (registrazione, accesso, logout), un pannello di amministrazione per il tuo sito web, un sistema per caricare i file, ecc.

Fortunatamente, alcune persone diverso tempo fa si sono rese conto che gli sviluppatori web incontrano problemi simili ogni volta che costruiscono un sito internet. Per questo motivo si sono uniti e hanno costruito dei framework (di cui Django fa parte) che offrono componenti già pronti per l'uso.

I frameworks esistono per evitare che tu debba reinventare la ruota e ti semplificano il lavoro quando crei un nuovo sito.

Perché ho bisogno di un framework?

Per capire Django, abbiamo bisogno di dare un'occhiata più da vicino ai server. La prima cosa che il server deve sapere è che vuoi che ti fornisca una pagina web.

Immagina una cassetta delle lettere che monitora tutte le lettere in entrata (richieste). Questo è ciò che fa un web server. Il web server legge le lettere, e invia una risposta con una pagina web. Ma quando vuoi inviare qualcosa, hai bisogno di avere qualche contenuto. E Django è ciò che ti aiuta a creare questo contenuto.

Cosa succede quando qualcuno richiede un sito Web dal tuo server?

Quando una richiesta arriva al web server, viene passata a Django che prova a capire che cosa é stato veramente richiesto. Django prende l'indirizzo della pagina web e cerca di capire cosa deve fare. Questa parte viene svolta da Django urlresolver (nota che l'indirizzo di una pagina web si chiama URL - Uniform Resource Locator -per cui il nome urlresolver acquista significato). Non é molto intelligente -ha bisogno di una serie di schemi e in seguito prova a far corrispondere l'URL. Django controlla questi modelli o schemi da cima a fondo e se qualcosa corrisponde a quel punto Django passa la richiesta alla funzione associata (che si chiama view).

Immagina un postino con una lettera. Sta camminando per la strada e controlla ogni numero civico mettendolo a confronto con quello sulla lettera. Se corrisponde, mette lì la lettera. Questo è il modo in cui l'urlresolver funziona!

Nella funzione view avvengono tutte le cose più interessanti: possiamo consultare un database alla ricerca di qualche informazione. Forse l'utente ha richiesto di cambiare qualcosa all'interno dei suoi dati? È come una lettera che dice "Per favore cambia la descrizione del mio lavoro". La view può controllare se sei autorizzata a farlo, poi aggiorna la descrizione del lavoro per te e manda un messaggio: "Fatto!". In seguito, la view genera una risposta e Django la può inviare al browser dell'utente.

Naturalmente, la descrizione qui sopra é molto semplificata, ma per il momento non hai bisogno di sapere nel dettaglio tutti gli aspetti tecnici. Avere il senso generale per il momento è abbastanza.

Per cui invece di perderci troppo nei dettagli, creeremo semplicemente qualcosa usando Django e apprenderemo i concetti fondamentali lungo la strada!

 

Il tuo primo progetto Django?

Creeremo un semplice blog!

Il primo passo è quello di iniziare un nuovo progetto di Django. Fondamentalmente, questo significa che eseguiremo alcuni script forniti da Django che creerà per noi lo scheletro di un progetto Django. Si tratta solo di un insieme di directory e file che verranno utilizzati dopo.

I nomi di alcuni file e cartelle sono molto importanti per Django. Non dovresti modificare i nomi dei file che stiamo per creare. Neanche spostarli in un altro posto è una buona idea. Django deve mantenere una determinata struttura per essere in grado di trovare le cose importanti.

Ricordati di eseguire tutto nel virtualenv. Se non vedi un prefisso (myvenv) nella tua console devi attivare il tuo virtualenv. Abbiamo spiegato come farlo nel capitolo installazione Django nella parte Lavorando con virtualenv. Digitando myvenv\Scripts\activate su Windows oppure source myvenv/bin/activate su Mac OS / Linux farà questo per te.

Dovresti eseguire nella tua console MacOS o Linux il seguente comando; non dimenticarti di aggiungere il punto . alla fine :

(myvenv) ~/blog$ django-admin startproject mysite .

Su Windows; non dimenticarti di aggiungere il punto . alla fine:

(myvenv) C:\Users\Name\blog> django-admin startproject mysite .

Il punto . è cruciale perché dice allo script d'installare Django nell'attuale directory (quindi il punto . è un riferimento di abbreviazione)

Nota Quando digiti i comandi sopra, ricorda che si digita soltanto la parte che inizia con django-admin oppure django-admin.py. Le parti mostrate qui come (myvenv) ~/blog$ e (myvenv) C:\Users\Name\blog> sono solo esempi del prompt che starà invitando il tuo input sulla tua command line.

django-admin.py è uno script che creerà le cartelle ed i file per te. Adesso dovresti avere una struttura di directory simile a questa:

blog              
├───manage.py
└───mysite
        settings.py
        urls.py
        wsgi.py
        __init__.py

manage.py è uno script che aiuta a gestire il sito. Usandolo saremo in grado di avviare un web server sul nostro computer senza dover installare nient'altro, tra l'altro.

Il file settings.py contiene la configurazione del tuo sito web.

Ricordi quando abbiamo parlato di un postino che controlla dove rilasciare la lettera? il file urls.pycontiene una lista di schemi usati da urlresolver.

Ignoriamo gli altri file per ora dal momento che non li modificheremo. L'unica cosa da ricordare è di non cancellarli per sbaglio!

Modificare le impostazioni

Facciamo qualche cambiamento in mysite/settings.py. Apri il file usando il code editor che hai installato prima.

Sarebbe bello avere l'ora corretta sul nostro sito Web. Vai alla lista di fusi orari di wikipedia e copia il tuo fuso orario (TZ). (es. Europe/Berlin)

In settings.py, trova la riga che contiene TIME_ZONE e modificala per scegliere il tuo fuso orario:

TIME_ZONE = 'Europe/Berlin'

Modifica "Europe/Berlin" nel modo corretto

Avrai anche bisogno di aggiungere un percorso per i file statici (scopriremo tutto su file statici e CSS più avanti nell'esercitazione). Scendi fino alla fine del file e sotto la voce STATIC_URL, aggiungi un nuovo percorso chiamato STATIC_ROOT:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

Imposta un database

Ci sono un sacco di software di database diversi che possono immagazzinare dati per il tuo sito. Noi useremo quello di default, sqlite3.

È già impostato in questa parte del file mysite/settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

Per creare un database per il nostro blog, eseguiamo questo nella console: python manage.py migrate (abbiamo bisogno di essere nella directory blog che contiene il file manage.py). Se funziona, dovresti vedere qualcosa di simile:

(myvenv) ~/djangogirls$ python manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: messages, staticfiles
  Apply all migrations: contenttypes, sessions, admin, auth
Synchronizing apps without migrations:
   Creating tables...
      Running deferred SQL...
   Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying sessions.0001_initial... OK

E abbiamo finito! Tempo di avviare il server web e vedere se il nostro sito Web funziona!

Devi essere nella directory che contiene il file di manage.py (la directory blog). Nella console, possiamo avviare il server web eseguendo python manage.py runserver:

(myvenv) ~/blog$ python manage.py runserver

Se sei su Windows e non funziona con UnicodeDecodeError, usa questo comando:

(myvenv) ~/blog$ python manage.py runserver 0:8000

Ora tutto quello che devi fare è controllare che il tuo sito sia in esecuzione. Apri il tuo browser (Firefox, Chrome, Safari, Internet Explorer o qualsiasi altro tu usi) e digita l'indirizzo:

http://127.0.0.1:8000/

Il server web assumerà il controllo del command prompt finché non lo fermi. Per digitare più comandi mentre è in esecuzione apri una nuova finestra di terminale e attiva il tuo virtualenv. Per fermare il server web, torna alla finestra dove è in esecuzione e premi i pulsanti CTRL+C - Control e C insieme (su Windows, è probabile che tu deva premere Ctrl+Break).

Congratulazioni! Hai appena creato il tuo primo sito e l'hai avviato usando un web server! Non è fantastico?

inparando Django 2.0

Modelli Django

Vogliamo creare un qualcosa che raccoglierà tutti i post del nostro blog. Per farlo, però, dobbiamo prima introdurre i cosiddetti oggetti.

Oggetti

Esiste un concetto nella programmazione chiamato programmazione orientata agli oggetti. L'idea è che invece di scrivere tutto come una noiosa sequenza di istruzioni di programmazione, possiamo modellare le cose e definire come esse interagiscono fra di loro.

Quindi cos'è un oggetto? È un insieme di proprietà ed azioni. Suona strano, ma ti faremo un esempio.

Se vogliamo modellare un gatto creeremo un oggetto Gatto che ha qualche proprietà, i.e. coloreetàumore (i.e. bravo, cattivo, sonnolento ;)), padrone (che è un oggetto Persona oppure, nel caso di un gatto randagio, questa proprietà è vuota).

E poi il Gatto ha alcune azioni: fusagraffiare oppure alimentare (nella quale daremo al gatto un po' di Cibo per gatti, che potrebbe essere un oggetto diverso con delle proprietà, i.e. gusto).

Gatto
--------
colore
età
umore
padrone
fare le fusa()
graffiare()
alimentare(cat_food)

Quindi in pratica l'idea è quella di descrivere cose vere in codice con delle proprietà (chiamate proprietà di oggetti) e azioni (chiamate metodi).

Quindi come faremo a modellare i post del blog? vogliamo costruire un blog, giusto?

Dobbiamo rispondere alla domanda: cos'è un post? Quali proprietà dovrebbe avere?

Beh, sicuramente il nostro post ha bisogno di qualche testo con il suo contenuto ed un titolo, vero? Sarebbe bello sapere chi l'ha scritto - quindi abbiamo bisogno di un autore. Infine, vogliamo sapere quando il post è stato creato e pubblicato.

Post
--------
titolo
testo
autore
data_creazione
data_pubblicazione

Che tipo di cose si potrebbero fare con un post? Sarebbe bello avere qualche metodo che pubblica il post, vero?

Quindi avremo bisogno di un metodo pubblicare.

Dal momento che sappiamo già cosa vogliamo ottenere, iniziamo a modellarlo in Django!

Modello Django

Sapendo cos'è un oggetto, possiamo creare un modello Django per il nostro post.

Un modello in Django è uno speciale tipo di oggetto - è salvato nel database. Un database è un insieme di dati. È un posto in cui archivierai informazioni sui tuoi utenti, sui tuoi post, ecc. Useremo un database SQLite per archiviare i nostri dati. Questo è l'adattatore Django di database predefinito -- ci basterà per adesso.

Puoi pensare ad un modello nel database come ad un foglio elettronico con colonne (campi) e righe (dati).

Creazione di un'applicazione

Per mantenere tutto ordinato, creeremo un'applicazione diversa all'interno del nostro progetto. È molto bello avere tutto organizzato fin dall'inizio. Per creare un'applicazione abbiamo bisogno di eseguire il seguente comando nella console (dalla cartella blog dove si trova il file manage.py):

(myvenv) ~/blog$ python manage.py startapp blog

Noterai che si è creata una nuova cartella blog e che ora contiene alcuni file. Le nostre cartelle ed i nostri file nel nostro progetto si dovrebbero vedere così:

blog          
├── mysite
|       __init__.py
|       settings.py
|       urls.py
|       wsgi.py
├── manage.py
└── blog
    ├── migrations
    |       __init__.py
    ├── __init__.py
    ├── admin.py
    ├── models.py
    ├── tests.py
    └── views.py

Dopo aver creato un'applicazione dobbiamo dire a Django che dovrebbe utilizzarla. Lo facciamo nel file mysite/settings.py. Dobbiamo trovare INSTALLED_APPS ed aggiungere una riga che contenga 'blog', appena sopra). Quindi il prodotto finale dovrebbe assomigliare a questo:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
)

Creazione di un modello blog post

Nel file blog/models.py definiamo tutti gli oggetti chiamati Models - Questo è il posto dove definiremo il nostro blog post.

Apriamo blog/models.py, cancella tutto quello che è lì e scrivi un codice come questo:

from django.db import models
from django.utils import timezone


class Post(models.Model):
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(
            default=timezone.now)
    published_date = models.DateTimeField(
            blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

Ricontrolla se stai utilizzando due caratteri di sottolineatura (_) su ciascun lato di str. Questa convenzione viene utilizzata spesso in Python e a volte li chiamiamo anche "dunder" (abbreviazione di "doppio carattere di sottolineatura").

Sembra spaventoso, vero? ma non ti preoccupare, ti spiegheremo cosa significano queste righe!

Tutte le righe che iniziano con from oppure con import sono righe che aggiungono alcuni pezzi da altri file. Quindi invece di copiare e incollare le stesse cose in ogni file, possiamo includere alcune parti con from ... import ....

class Post(models.Model): - questa riga definisce il nostro modello (è un oggetto).

  • class è una parola chiave speciale che indica che stiamo definendo un oggetto.
  • Post è il nome del nostro modello. Possiamo dargli un nome diverso (ma dobbiamo evitare caratteri speciali e spazi). Inizia sempre il nome di una classe con un lettera maiuscola.
  • models.Model significa che il Post è un modello Django, quindi Django sa che dovrebbe essere salvato nel database.

Ora definiamo le proprietà di cui stavamo parlando: titolo, testo, data_creazione, data_pubblicazione e autore. Per fare ciò dobbiamo definire un tipo per ogni campo (è un testo? Un numero? Una data? Una relazione con un altro oggetto, i.e. un utente?).

  • models.CharField - così si definisce un testo con un numero limitato di lettere.
  • models.TextField - questo è il codice per definire un testo senza un limite. Sembra l'ideale per i contenuti di un post, vero?
  • models.DateTimeField - questo per la data ed l'ora.
  • models.ForeignKey - questo è un link a un altro modello.

Non spiegheremo ogni pezzo di codice perchè ci vorrebbre troppo tempo. Dovresti dare un'occhiata alla documentazione di Django se vuoi saperne di più sui campi di un modello e come definire altre cose rispetto a quelle descritte sopra (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types).

Che dire di def publish(self):? È esattamente il metodo pubblicare di cui stavamo parlando prima. def significa che questa è una funzione/metodo e publish è il nome del metodo. Puoi modificare il nome del metodo, se vuoi. La regola per la denominazione è usare lettere minuscole e caratteri di sottolineatura al posto degli spazi. Per esempio, un metodo che calcola il prezzo medio potrebbe essere chiamato calculate_average_price.

I metodi spesso restituiscono qualcosa. C'è un esempio nel metodo __str__. In questo caso, quando chiamiamo __str__() otterremo un testo (stringa) con il titolo del Post.

Se c'è qualcosa di poco chiaro sui modelli, sentiti libera/o di chiedere al tuo coach! Sappiamo che è complicato, soprattutto quando impari cosa sono gli oggetti e le funzioni allo stesso tempo. Ma speriamo che sembri un po' meno magico per te per adesso!

Crea tabelle per i modelli nel tuo database

L'ultimo passo è quello di aggiungere un nuovo modello al nostro database. Prima dobbiamo far sapere a Django che ci sono alcuni cambiamenti nel nostro modello (l'abbiamo appena creato!). Digita python manage.py makemigrations blog. Il risultato somiglierà a questo:

(myvenv) ~/blog$ python manage.py makemigrations blog
Migrations for 'blog':
  0001_initial.py:
  - Create model Post

Django ci ha preparato un file di migrazione che dobbiamo applicare nel nostro database. Digita python manage.py migrate blog e l'output dovrebbe essere:

(myvenv) ~/blog$ python manage.py migrate blog
Operations to perform:
  Apply all migrations: blog
Running migrations:
  Rendering model states... DONE
  Applying blog.0001_initial... OK

Evviva! Il nostro modello Post ora è nel database! Sarebbe bello poterlo vedere, vero? Vai al prossimo capitolo per vedere com'è il tuo Post!

Django admin

Per aggiungere, modificare e cancellare i post che abbiamo appena strutturato useremo Django admin.

Apri il file blog/admin.py e sostituisci il suo contenuto con:

from django.contrib import admin
from .models import Post

admin.site.register(Post)

Come puoi vedere, stiamo importando (include) il modello di Post che abbiamo definito nel capitolo precedente. Per far si che il nostro modello sia visibile nella pagina di admin, dobbiamo registrare questo modello con admin.site.register(Post).

OK, è tempo di guardare il nostro modello Post. Ricorda di eseguire python manage.py runserver nella console per avviare il web server. Vai nel browser e scrivi l'indirizzo http://127.0.0.1:8000/admin/ Vedrai una pagina di login come questa:

Login page

Per accedere, devi creare un superuser - un utente che ha il controllo su tutto nel sito. Torna alla command-line e digita python manage.py createsuperuser, e premi invio. Quando richiesto, digita il tuo username (minuscole, senza spazi), indirizzo e-mail e password. Non ti preoccupare se non riesci a vedere la password che stai digitando - è così che dovrebbe essere. Basta digitarlo e premere invio per continuare. L'output dovrebbe essere così (dove il nome utente e l'email dovrebbero essere i tuoi):

(myvenv) ~/blog$ python manage.py createsuperuser
Username: admin
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.

Torna nel tuo browser e fai il log in con le credenziali di superuser che hai scelto, dovresti vedere la dashboard d'amministrazione di Django.

L'admin di Django

Vai su Post ed sperimenta un po'. Aggiungi cinque o sei post. Non preoccuparti del contenuto - puoi semplicemente fare il copia-incolla di parti di testo da questo tutorial per risparmiare tempo :).

Assicurati che almeno due o tre post (ma non tutti) abbiano la data in cui sono stati pubblicati. Ti sarà utile più tardi.

L'admin di Django

Se vuoi sapere di più riguardo l'admin di Django, dovresti dare un'occhiata alla documentazione di Django: https://docs.djangoproject.com/en/2.2/ref/contrib/admin/

Questo è un buon momento per andare a prendere un caffè (o tè) o qualcosa da mangiare per riprendere le forze. Hai creato il tuo primo modello Django - ti meriti una piccola pausa!

Django URL

Stiamo per costruire la nostra pagina web: una homepage per il tuo blog! Ma prima, impariamo un po' di più sulle url di Django.

Che cos'è un URL?

Una URL è semplicemente un indirizzo web. Puoi vedere una URL ogni volta che visiti un sito web - si vede nella barra degli indirizzi del tuo browser. (sì! 127.0.0.1:8000 is a URL! Anche https://blog.org è una URL):

Url

Ogni pagina internet ha bisogno della sua URL. In questo modo la tua applicazione sa cosa deve mostrare a un utente che visita una URL. In Django usiamo qualcosa chiamato URLconf ( configurazione dell'URL). URLconf è un insieme di modelli che Django cercherà di far corrispondere con l'URL ricevuta per trovare la view giusta.

Come funzionano le URL in Django?

Apriamo il file mysite/urls.py nel code editor che hai scelto e vediamo com'è:

from django.urls import path, include
from django.contrib import admin

urlpatterns = [
    # Examples:
    # path('', 'mysite.views.home', name='home'),
    # path('blog/', include('blog.urls')),

    path('admin/', include(admin.site.urls)),
]

Come puoi vedere, Django ha già predisposto qualcosa per noi in questo file.

Le righe che iniziano con # sono commenti - questo significa che non verranno lette da Python. Comodo, non è vero?

L'admin URL , che hai visto nel capitolo precedente è già qui:

    path('admin/', include(admin.site.urls)),

Questo significa che per ogni URL che comincia con admin/ Django troverà la corrispondente view. In questo caso stiamo includendo un sacco di admin URL così che non sia tutto imballato in questo piccolo file - è più leggibile e più pulito.

La tua prima Url Django!

È ora di creare la tua prima URL. Vogliamo usare http://127.0.0.1:8000/ come homepage per il nostro blog e visualizzare il nostro elenco di post.

Vogliamo anche mantenere il file di mysite/urls.py pulito, quindi importeremo le url dalla nostra applicazione blog sul file principale mysite/urls.py.

Vai avanti, elimina le righe commentate (che cominciano con #) e aggiungi una riga che importerà blog.urls nella url principale ('').

Il tuo file mysite/urls.py ora dovrebbe avere questo aspetto:

from django.urls import path, include
from django.contrib import admin

urlpatterns = [
    path('admin/', include(admin.site.urls)),
    path('', include('blog.urls')),
]

Django reindirizzerà ora tutto ciò che viene da 'http://127.0.0.1:8000/' verso blog.urls e cercherà ulteriori istruzioni in questo file.

Quando si scrivono espressioni regolari in Python lo si fa sempre con r davanti alla stringa. Questo è un suggerimento utile per Python che la stringa possa contenere caratteri speciali che non sono destinati per lo stesso Python, ma per l'espressione regolare.

blog.urls

Crea un nuovo file blog/urls.py. Perfetto! Ora aggiungi queste prime due righe:

from django.urls import path
from . import views

Stiamo solo importando metodi che appartengono a Django e tutte le nostre views dalla nostra app blog (non abbiamo ancora nulla all'interno, ma rimedieremo a questo in un minuto!)

Dopo di che, possiamo aggiungere il nostro primo modello di URL:

urlpatterns = [
    path('', views.post_list, name='post_list'),
]

Come vedi, stiamo assegnando una view nominata post_list alla URL ^$. Questa espressione regolare combinerà^ (un inizio) seguito da $ (una fine) - cosicché solo una stringa vuota possa combaciare. È giusto, perché nei resolver di URL di Django, ' http://127.0.0.1:8000 /' non è una parte dell'URL. Questo schema dirà a Django che views.post_list è il posto giusto dove andare se qualcuno entra nel tuo sito all'indirizzo 'http://127.0.0.1:8000/'.

L'ultima parte name='post_list' è il nome dell'URL che verrà usata per identificare la view. Può avere lo stesso nome della view, ma può anche essere qualcosa di completamente diverso. Useremo le URL rinominate successivamente nel progetto quindi è importante dare un nome a ciascuna URL nell'app. Inoltre dovremmo cercare di mantenere i nomi delle URL unici e facili da ricordare.

Tutto fatto? Apri http://127.0.0.1:8000 / nel tuo browser per vedere il risultato.

Errore

Non funziona, vero? Non ti preoccupare, è solo una pagina di errore, niente di cui spaventarsi! In realtà sono molto utili:

Leggerai che non c'è un attributo 'post_list. il post_list ti ricorda qualcosa? Abbiamo chiamato la nostra view proprio così! Questo significa che è tutto a posto. Semplicemente non abbiamo ancora creato la nostra view. Non ti preoccupare, ci arriveremo.

Se vuoi sapere di più sulla configurazione di URL Django,

vai alla documentazione ufficiale: https://docs.djangoproject.com/en/2.2/topics/http/urls/

Le views di Django - è arrivata l'ora di creare!

È ora di liberarsi di quel bug che abbiamo creato nel capitolo precedente :)

Una view è un posto dove viene messa la "logica" della nostra applicazione. Essa richiederà informazioni dal modello che hai creato prima e lo passerà ad un template. Creeremo un template nel prossimo capitolo. Le views sono solo metodi di Python un po' più complicati di quelli che abbiamo descritto nel capitolo Introduzione a Python.

Le views vengono collocate nel file views.py. Noi aggiungeremo le nostre views nel file 

blog/views.py

blog/views.py

OK, apriamo questo file e scopriamo cosa c'è dentro:

from django.shortcuts import render
# Create your views here.

Non c'è molto per ora. La view più semplice può essere simile a questa.

def post_list(request):
    return render(request, 'blog/post_list.html', {})

Come puoi vedere, abbiamo creato un metodo (def) chiamato post_list che prende request e restituisce un metodo render che ci fornirà (metterà insieme) il nostro template blog/post_list.html.

Salva il file, vai su http://127.0.0.1:8000/ e guarda cosa abbiamo ottenuto.

Un altro errore! Leggi cosa sta succedendo adesso:

Error

Questo è facile: TemplateDoesNotExist. Sistemiamo il bug e creiamo un template nel prossimo capitolo!

Impara di più sulle views di Django leggendo la documentazione ufficiale:

https://docs.djangoproject.com/en/2.2/topics/http/views/

Introduzione all'HTML

Ti potresti chiedere, cos'è un template?

Un template è un file che possiamo riutilizzare per presentare informazioni diverse in un formato consistente - per esempio, potresti utilizzare un template per aiutarti a scrivere una lettera, perché anche se ciascuna lettera potrebbe contenere un messaggio diverso ed essere a sua volta indirizzata ad una persona diversa, condivideranno lo stesso formato.

Un template Django viene descritto in un linguaggio chiamato HTML (è lo stesso HTML che abbiamo menzionato nel primo capitolo Come funziona l'Internet).

Cos'è l'HTML?

HTML è un semplice codice che viene interpretato dal tuo browser - come Chrome, Firefox o Safari - per rendere un sito web visibile all'utente.

HTML sta per "HyperText Markup Language". HyperText significa che è un tipo di testo che supporta i collegamenti ipertestuali tra le pagine. Markup significa che abbiamo preso un documento e l'abbiamo contrassegnato con il codice per dire a qualcosa (in questo caso, un browser) come interpretare la pagina. Il codice HTML è costruito con tags, ognuno inizia con < e finisce con >. Questi tag rappresentano gli elementi di markup.

Il tuo primo template!

Creare un template significa creare un file template. Tutto è un file, vero? Probabilmente l'hai già notato.

I template vengono salvati in una cartella blog/templates/blog. Quindi prima crea una directory chiamata templates nella directory del tuo blog. Quindi crea un'altra directory chiamata blogall'interno della tua directory templates:

blog
└───templates
    └───blog

(Ti chiederai perché abbiamo bisogno di due directory chiamate entrambe blog - come scoprirai più tardi, si tratta semplicemente di una denominazione convenzionale che serve a rendere la vita più facile.)

E ora crea un file post_list.html nella directory blog/templates/blog (lascialo in bianco per adesso).

Guarda che aspetto ha il tuo sito adesso: http://127.0.0.1:8000

Se continui ad avere un errore TemplateDoesNotExists, prova a riavviare il server. Vai nella command line, arresta il server premendo Ctrl+C ( I tasti Control e C insieme) e riavvialo utilizzando il comando python manage.py runserver.

Figura 11.1

L'errore non c'è più! Congratulazioni :) Tuttavia, il tuo sito in realtà non sta pubblicando niente eccetto una pagina vuota, perché anche il tuo template è vuoto. Dobbiamo sistemarlo.

Aggiungi quanto segue nel tuo file template:

<html>
    <p>Hi there!</p>
    <p>It works!</p>
</html>

Quindi come appare il tuo sito ora? Clicca per scoprirlo: http://127.0.0.1:8000/

Figura 11.2

Ha funzionato! Ottimo lavoro :)

  • Il comando più basico, <html>, è sempre l'inizio di ogni pagina web e </html> è sempre la fine. Come puoi vedere, l'intero contenuto del sito va tra il tag iniziale <html> ed il tag conclusivo </html>
  • <p> è un tag per gli elementi paragrafo; </p> conclude ogni paragrafo

Head & body

Ciascuna pagina HTML è a sua volta divisa in due elementi: head e body.

  • head è un elemento che contiene informazioni sul documento non visibili sullo schermo.

  • body è l'elemento che contiene tutto ciò che invece viene visualizzato come parte della pagina web.

Utilizziamo <head> per dire al browser come interpretare la configurazione della pagina, e <body> per dirgli in realtà cosa c'è nella pagina.

Per esempio, puoi mettere un elemento di titolo all'interno di <head>, così:

<html>
    <head>
        <title>Ola's blog</title>
    </head>
    <body>
        <p>Hi there!</p>
        <p>It works!</p>
    </body>
</html>

Salva il file e aggiorna la tua pagina.

Figura 11.3

Hai notato come il browser ha capito che "Il blog di Ola" è il titolo della tua pagina? Ha interpretato <title>Il blog di Ola</title> ed ha messo il testo nella barra del titolo sul tuo browser (sarà anche utilizzato per i segnalibri e così via).

Probabilmente hai anche notato che ogni tag di apertura è abbinato ad un tag di chiusura, con un /, e che gli elementi sono annidati (i.e. non puoi chiudere un tag particolare fino a quando tutti quelli che erano al suo interno sono stati chiusi a loro volta).

È come mettere le cose in delle scatole. Hai una grossa scatola, <html></html>; al suo interno c'è <body></body>, che contiene scatole ancora più piccole: <p></p>.

Devi seguire queste regole di tag di chiusura, e di elementi annidati - se non lo fai, il browser potrebbe non essere in grado di interpretarli correttamente e la tua pagina verrà visualizzata incorrettamente.

Personalizza il tuo template

Ora puoi divertirti un po' e provare a personalizzare il tuo template! Qua ci sono un po' di tag utili per quello:

  • <h1>Un'intestazione</h1> - per la tua intestazione più importante
  • <h2>Un sottotitolo</h2> per un titolo di livello inferiore
  • <h3>Un sottotitolo più piccolo</h3> ... e così via, fino a <h6>
  • <em>text</em> enfatizza il tuo testo
  • <strong>text</strong> enfatizza fortemente il tuo testo
  • <br /> va in un'altra riga (puoi mettere qualsiasi cosa dentro br)
  • <a href="https://djangogirls.org">link</a> crea un link
  • <ul><li>primo elemento</li><li>secondo elemento</li></ul> fa una lista, proprio come questa qui!
  • <div></div> definisce una sezione della pagina

Qui c'è un esempio di un template completo:

<html>
    <head>
        <title>Myblog</title>
    </head>
    <body>
        <div>
            <h1><a href="">my Blog</a></h1>
        </div>

        <div>
            <p>published: 14.06.2014, 12:14</p>
            <h2><a href="">My first post</a></h2>
            <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
        </div>

        <div>
            <p>published: 14.06.2014, 12:14</p>
            <h2><a href="">My second post</a></h2>
            <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.</p>
        </div>
    </body>
</html>

Abbiamo creato tre sezioni div qui.

  • Il primo elemento div contiene il titolo del nostro blog - è un'intestazione ed un link
  • Altri tre elementi div contengono i nostri post con la loro data di pubblicazione, h2 con il titolo di un post che è cliccabile e due p (paragrafi) di testo, uno per la data e l'altro per i nostri post.

Ci dà questo effetto:

Figura 11.4

Yaaay! Ma fino adesso, il nostro template mostra esattamente la stessa informazione - mentre prima stavamo dicendo che i template ci permettono di mostrare diverse informazioni nello stesso formato.

Quello che vogliamo è visualizzare i veri post aggiunti nel nel nostro Django admin - è quello che faremo adesso.

Django ORM e i QuerySet

In questo capitolo imparerai come Django si collega al database e archivia i dati al suo interno. Tuffiamoci!

Cos'è un QuerySet?

Un QuerySet, in sostanza, è una lista di oggetti di un determinato Modello. Il QuerySet ti permette di leggere il dato dal database, filtrarlo e ordinarlo.

È più facile impararlo con un esempio. Proviamo, ti va?

La shell di Django

Apri la tua console locale (non su PythonAnywhere) e digita questo comando:

(myvenv) ~/blog$ python manage.py shell

L'effetto dovrebbe essere come questo:

(InteractiveConsole)
>>>

Ora ti trovi nella consolle interattiva di Django. È come il prompt di python ma con un po' di magia di Django in più :). Qui puoi anche utilizzare tutti i comandi Python, ovviamente.

Tutti gli oggetti

Proviamo a rendere visibili tutti i nostri post prima. Puoi farlo con il seguente comando:

>>> Post.objects.all()
Traceback (most recent call last):
      File "<console>", line 1, in <module>
NameError: name 'Post' is not defined

Ops! È comparso un errore. Ci dice che non c'è nessun Post. È corretto -- ci siamo dimenticati di importarlo!

>>> from blog.models import Post

È semplice: importiamo il modello Post da blog.models. Proviamo a rendere di nuovo visibili tutti i post:

>>> Post.objects.all()
<QuerySet [<Post: my post title>, <Post: another post title>]>

È una lista di post che abbiamo creato prima! Abbiamo creato questi post usando l'interfaccia di ammisnistrazione di Django. Comunque sia, ora vogliamo creare nuovi post usando Python, quindi come lo facciamo?

Creare oggetti

Così si crea un nuovo oggetto Post nel database:

>>> Post.objects.create(author=me, title='Sample title', text='Test')

Ma manca un ingrediente qui: me. Dobbiamo passare un'istanza del modello User come un autore. Come si fa?

Importiamo il modello User prima:

>>> from django.contrib.auth.models import User

Quali utenti abbiamo nel nostro database? Prova questo:

>>> User.objects.all()
<QuerySet [<User: ola>]>

È il superuser che abbiamo creato prima! Ora prendiamo un'istanza del user:

me = User.objects.get(username='ola')

Come puoi vedere, ora prendiamo (get) un User con un username che è uguale a 'ola'. Ben fatto, devi cambiarlo con il tuo username.

Adesso possiamo finalmente creare il nostro post:

>>> Post.objects.create(author=me, title='Sample title', text='Test')

Evviva! Vuoi controllare se funziona?

>>> Post.objects.all()
<QuerySet [<Post: my post title>, <Post: another post title>, <Post: Sample title>]>

Eccolo, un altro post nell'elenco!

Aggiungi altri post

Ora puoi divertirti un po' ed aggiungere altri post per vedere come funziona. Aggiungi altri 2 o 3 e vai alla prossima parte.

Filtrare gli oggeti

Larga parte parte dei QuerySet consiste nell'abilità di filtrarli. Diciamo che vogliamo trovare tutti i post che hanno come autore l'Utente ola. Useremo filter invece di all in Post.objects.all(). Tra parentesi affermeremo le condizioni che un blog post deve soddisfare per finire nel nostro queryset. Nella nostra situazione è autore che è uguale a me. Il modo di scriverlo in Django è autore=me. Ora il nostro pezzo di codice ha questo aspetto:

>>> Post.objects.filter(author=me)
<QuerySet [<Post: Sample title>, <Post: Post number 2>, <Post: My 3rd post!>, <Post: 4th title of post>]>

O magari vogliamo vedere tutti i post che contengono la parola 'titolo' nel campo titolo?

>>> Post.objects.filter(title__contains='title')
<QuerySet [<Post: Sample title>, <Post: 4th title of post>]>

Nota ci sono due caratteri di sottolineatura (_) tra titolo e contains. L'ORM di Django usa questa sintassi per separare i nomi dei campi ("titolo") ed operazioni o filtri ("contiene"). Se usi solo un carattere di sottolineatura, otterrai un errore come "FieldError: non è possibile risolvere la parola chiave title_contains".

Puoi anche ottenere una lista di tutti i post pubblicati. Lo facciamo filtrando tutti i post che hanno una published_date impostata in passato:

>>> from django.utils import timezone
>>> Post.objects.filter(published_date__lte=timezone.now())
[]

Purtroppo, il post che abbiamo aggiunto dalla console Python non è ancora pubblicato. Possiamo modificarlo! In primo luogo ottenere un'istanza di un post che vogliamo pubblicare:

>>> post = Post.objects.get(title="Sample title")

Ora pubblicalo con il nostro metodo publish!

>>> post.publish()

Ora cerca di ottenere di nuovo l'elenco dei post pubblicati (premere il pulsante di freccia in su 3 volte e premere invio):

>>> Post.objects.filter(published_date__lte=timezone.now())
<QuerySet [<Post: Sample title>]>

Ordinare gli oggetti

I QuerySet ti permettono anche di ordinare le liste di oggetti. Proviamo a ordinarli in base al campo created_date:

>>> Post.objects.order_by('created_date')
<QuerySet [<Post: Sample title>, <Post: Post number 2>, <Post: My 3rd post!>, <Post: 4th title of post>]>

Possiamo anche invertire l'ordine aggiungendo - all'inizio:

>>> Post.objects.order_by('-created_date')
<QuerySet [<Post: 4th title of post>, <Post: My 3rd post!>, <Post: Post number 2>, <Post: Sample title>]>

QuerySet di concatenamento

Puoi anche combinare QuerySet concatenandole insieme:

>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

È davvero potente e ti permette di scrivere query piuttosto complesse.

Fantastico! Ora sei pronta per la prossima parte! Per chiudere la shell, digita questo:

>>> exit()
$

I dati dinamici nei templates

Abbiamo diversi pezzi: il modello Post è definito in models.py, abbiamo post_list nel file views.py ed abbiamo aggiunto il template. Ma come faremo a far comparire i nostri post nel nostro template HTML? Perché questo è quello che vogliamo: prendere qualche contenuto (modelli salvati nel database) e farlo vedere in modo carino nel nostro template, giusto?

Questo è esattamente quello che le views dovrebbero fare: collegare i modelli ed i template. Nella nostra post_list view avremo bisogno di prendere i modelli che vogliamo far vedere e passarli nel template. Quindi praticamente nella view decidiamo cosa (modello) renderemo visibile nel template.

OK, quindi come facciamo a farlo?

Dobbiamo aprire il nostro blog/views.py. Per ora post_list view si vede così:

from django.shortcuts import render

def post_list(request):
    return render(request, 'blog/post_list.html', {})

Ricordi quando abbiamo parlato di includere codice scritto in diversi file? Ora è il momento di includere il model che abbiamo scritto in models.py. Aggiungeremo questa riga from .models import Post così:

from django.shortcuts import render
from .models import Post

Il punto dopo il from significa directory attuale oppure applicazione attuale. Dal momento che views.py e models.py sono nella stessa directory possiamo semplicemente utilizzare . ed il nome del file (senza .py). Allora importiamo il nome del modello (Post).

Cos'altro bisogna fare? Per poter prendere i post del blog dal modelloPost ci serve una cosa chiamata QuerySet.

QuerySet

Dovresti già sapere come funziona QuerySet. Ne abbiamo parlato nel capitolo Django ORM (QuerySets) .

Quindi ora ci interessa una lista di post del blog che sono pubblicati e organizzati da published_date, giusto? Lo abbiamo già fatto nel capitolo sulle QuerySet!

Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')

Adesso mettiamo questo pezzo di codice nel file blog/views.py aggiungendolo alla funzione def post_list(request):

from django.shortcuts import render
from django.utils import timezone
from .models import Post

def post_list(request):
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    return render(request, 'blog/post_list.html', {})

Nota che abbiamo creato una variabile per il nostro QuerySet: posts. Vedila come il nome del nostro QuerySet. Da qui in avanti possiamo riferirci ad esso con questo nome.

Il codice utilizza anche la funzione timezone.now(), quindi dobbiamo aggiungere un import per timezone.

L'ultima cosa che manca &#xE8; passare la QuerySet posts nel template (ci occuperemo di come renderlo visibile nel prossimo capitolo).

Nella funzione render abbiamo già un parametro con request (quindi tutto quello che riceviamo dal nostro utente via internet) e un file template 'blog/post_list.html'. Nell'ultimo parametro, che è simile a questo: {} possiamo aggiungere cose che il template possa utilizzare. Dobbiamo dargli un nome (ci atterremo a 'posts' per il momento :)). Si vede così: {'posts': posts}. Ti preghiamo di notare che la parte prima di : è una stringa; devi metterla tra virgolette ''..

Il nostro file blog/views.py dovrà risultare così:

from django.shortcuts import render
from django.utils import timezone
from .models import Post

def post_list(request):
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    return render(request, 'blog/post_list.html', {'posts': posts})

È tutto! Ora di tornare al nostro template e rendere visibile questo QuerySet!

Se vuoi leggere di più sui QuerySets in Django dovresti dare un'occhiata qui: 

https://docs.djangoproject.com/en/2.2/ref/models/querysets/

I templates di Django

È l'ora di visualizzare alcuni dati! Django ci dà alcuni template tags già pronti per farlo.

Cosa sono i template tags?

In HTML non puoi scrivere codice Python, perché i browser non lo capiscono. Essi conoscono solo l'HTML. Noi sappiamo che l'HTML è piuttosto statico, mentre Python è molto più dinamico.

Django template tags ci permettono di trasferire le cose simili a Python in HTML, in modo che tu possa costruire siti web in modo più veloce e facile. Accidenti!

Mostra il template con la lista di post

Nel capitolo precedente abbiamo dato al nostro template una lista di posts nella variabile posts. Adesso lo mostreremo nell'HTML.

Per stampare una variabile nel template Django, usiamo doppie parentesi graffe con il nome della variabile all'interno, così:

{{ posts }}

Prova questo nel tuo template blog/templates/blog/post_list.html. Sostituisci tutto dal secondo <div> al terzo </div> con {{ posts }}. Salva il file e aggiorna la pagina per vedere i risultati:

Come vedi, quello che abbiamo è:

<QuerySet [<Post: My second post>, <Post: My first post>]>

Significa che Django lo vede come una lista di oggetti. Ricordi dalla Introduzione a Python come possiamo rendere visibili le liste? Sì, con for loops! In un template Django si fanno così:

{% for post in posts %}
    {{ post }}
{% endfor %}

Funziona! Ma noi vogliamo che vengano mostrate come i post statici che abbiamo creato prima nel capitolo Introduzione ad HTML. Puoi mischiare i tag HTML con quelli di template. Il nostro body avrà questo aspetto:

<div>
    <h1><a href="/">my Blog</a></h1>
</div>

{% for post in posts %}
    <div>
        <p>published: {{ post.published_date }}</p>
        <h1><a href="">{{ post.title }}</a></h1>
        <p>{{ post.text|linebreaksbr }}</p>
    </div>
{% endfor %}

Tutto quello che hai messo tra {% for %} e {% endfor %} Sarà ripetuto per ciascun oggetto della lista. Aggiorna la tua pagina:

Ti sei accorto che abbiamo utilizzato una notazione leggermente diversa questa volta {{ post.title }} oppure {{ post.text }}? Stiamo introducendo i dati in ciascuno dei campi definiti nel nostro modello Post. Inoltre le |linebreaksbr stanno spingendo il testo dei post attraverso un filtro per trasformare le line-breaks in paragrafi.

CSS - dagli un bel aspetto!

Il nostro blog sembra ancora un pochino brutto, vero? È arrivato il momento di abbellirlo! Per fare ciò useremo CSS.

Che cos'è CSS?

Cascading Style Sheets (CSS) è un linguaggio usato per descrivere l'aspetto e la formattazione di un sito scritto in un linguaggio di markup (come HTML). Vedilo come il trucco del nostro sito ;).

Ma non vogliamo ricominciare da capo, giusto? Ancora una volta useremo qualcosa preparato da altri programmatori disponibile su Internet gratuitamente per tutti. Si sa, re-inventare la ruota non è molto divertente.

Usiamo Bootstrap!

Bootstrap è uno dei più popolari framework HTML e CSS per costruire bellissimi siti internet: https://getbootstrap.com/

È stato scritto da programmatori che lavoravano per Twitter ed è ora sviluppato da volontari da ogni parte del mondo.

Installa Bootstrap

Per installare Bootstrap, avrai bisogno di aggiungere questo nel tag <head> del tuo file .html (blog/templates/blog/post_list.html):

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

Le due linee sopra riportate non aggiungono nessun file al tuo progetto. Stanno solo reindirizzando ad alcuni files the esistono in internet. Ma non ti preoccupare troppo, vai avanti e apri la tua pagina web e ricarica la pagina. Eccolo qui!

Figura 14.1

Sembra già più carino!

File statici in Django

Infine, daremo uno sguardo più approfondito a quelli che abbiamo chiamato file statici. I file statici sono tutti i tuoi CSS e le immagini -- file che non sono dinamici, il loro contenuto non dipende dal contesto della richiesta e sarà lo stesso per ogni utente.

Dove mettere i file statici in Django

Come hai visto quando abbiamo eseguito collectstatic sul server, Django sa già dove trovare i file statici per l'app built-in "admin". Ora dobbiamo solo aggiungere alcuni file statici per la nostra app, blog.

Lo facciamo creando una cartella denominata static all'interno dela nostra app blog:

blog          
├── blog
│   ├── migrations
│   ├── static
│   └── templates
└── mysite

Django troverà automaticamente tutte le cartelle chiamate "static" dentro le cartelle delle tua app, e sarà in grado di utilizzare il loro contenuto come file statici.

Il tuo primo file CSS!

Ora, creiamo un file CSS, per poter aggiungere il tuo stile personale al tuo sito. Crea una nuova cartella dal nome css all'interno della tua cartella static. Poi, crea un nuovo file all'interno della tua cartella css e chiamalo blog.css. Fatto?

blog
└─── blog
     └─── static
          └─── css
               └─── blog.css

È giunto il momento di scrivere un po' di CSS! Apri il file static/css/blog.css nel tuo editor di codice.

Non ci dilungheremo troppo sul come personalizzare e imparare CSS in questo momento, dal momento che è abbastanza facile e puoi impararlo da solo/a alla fine di questo workshop. Ti raccomandiamo caldamente di seguire questo corso Codeacademy HTML & CSS course per imparare tutto quello che serve sapere per poter rendere più bello un sito internet con CSS.

Facciamo comunque un esempio. Perchè non cambiare il colore del nostro header? Per decifrare i colori, i computer usano dei codici speciali. Questi codici cominciano con # a cui fanno seguito 6 caratteri, sia lettere (A-F) che numeri (0-9). Puoi trovare vari esempi di codici colore qui: http://www.colorpicker.com/. Puoi anche usare colori predefiniti come ad esempio red e green.

Aggiungi il seguente codice nel tuo file static/css/blog.css:

h1 a {
    color: #FCA205;
}

h1 a è un esempio di selettore CSS. Questo significa che stiamo cercando di cambiare lo stile su tutti gli elementi a all'interno di un elemento h1 (in questo caso, abbiamo una linea di codice così strutturata: <h1><a href="">link</a></h1>). In questo caso, stiamo cercando di cambiare il colore con #FCA205, che corrisponde all'arancione. Ovviamente puoi mettere il codice di qualsiasi altro colore tu preferisca!

In un file CSS definiamo lo stile degli elementi presenti nel file HTML. Gli elementi in questione vengono identificati con il nome (ad esempio a, h1, body) oppure con l'attributo class o l'attributo id. Class e id sono i nomi che assegni agli elementi. Le classi definiscono gruppi di elementi mentre gli id indicano uno specifico elemento. Ad esempio, il seguente elemento può essere identificato nel CSS utilizzando il nome del tag a, la classe external_link oppure l'id link_to_wiki_page:

<a href="https://en.wikipedia.org/wiki/Django" class="external_link" id="link_to_wiki_page">

Per saperne di più puoi leggere CSS Selectors in w3schools.

Infine, dobbiamo anche far sapere al nostro template in HTML che abbiamo effettivamente aggiunto un po' di CSS. Apri il file blog/templates/blog/post_list.html e aggiungi la seguente riga di testo:

{% load staticfiles %}

Per ora stiamo solamente caricando tutti i nostri static files :). Aggiungi questa riga di testo tra <head> e </head>, subito dopo il link al file CSS di Bootstrap (il browser legge i file nell'ordine in cui sono dati, per cui il codice nei nostri files può sovrascrivere il codice presente nei files di Bootstrap):

<link rel="stylesheet" href="{% static 'css/blog.css' %}">

Stiamo dicendo al nostro template dove trovare i nostri file CSS.

Il tuo file dovrebbe avere questo aspetto:

{% load staticfiles %}
<html>
    <head>
        <title>My Blog</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    </head>
    <body>
        <div>
            <h1><a href="/">My Blog</a></h1>
        </div>

        {% for post in posts %}
            <div>
                <p>published: {{ post.published_date }}</p>
                <h1><a href="">{{ post.title }}</a></h1>
                <p>{{ post.text|linebreaksbr }}</p>
            </div>
        {% endfor %}
    </body>
</html>

OK, salviamo il file e ricarichiamo la pagina web!

learning django

Ben fatto! Adesso potremmo dare un po' più d'aria alla nostra pagina web e aumentare il margine nella parte sinistra. Proviamo!

body {
    padding-left: 15px;
}

Aggiungi questo al tuo CSS, salva il file e guarda il risultato!

inèparando django framework

Potremmo anche personalizzare lo stile calligrafico nel nostro header. Incolla quanto segue all'interno del tag <head> che si trova nel file blog/templates/blog/post_list.html:

<link href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css">

Questa riga consente di importare un font chiamato Lobster da Google Fonts (https://www.google.com/fonts).

Ora aggiungi font-family: 'Lobster'; nel file CSS static/css/blog.css all'interno del blocco h1 a (il codice tra le due parentesi graffe, { e }) e ricarica la pagina:

h1 a {
    color: #FCA205;
    font-family: 'Lobster';
}

learning django

Grandioso!

Come già accennato, il CSS utilizza il concetto di 'classe' che in pratica ti permette di assegnare uno specifico nome ad una parte del tuo documento HTML e di applicare uno stile solo a questa parte senza cambiare il resto. È di grande aiuto quando hai due div che hanno funzioni differenti (ad esempio uno è un header e l'altro un post), e non vuoi che appaiano uguali.

Prova a dare dei nomi ad alcune parti dell'HTML. Aggiungi una classe chiamta page-header al tuo div che contiene l'intestazione così:

<div class="page-header">
    <h1><a href="/">My Blog</a></h1>
</div>

E ora aggiungi una classe post al tuo div che contiene un articolo del blog.

<div class="post">
    <p>published: {{ post.published_date }}</p>
    <h1><a href="">{{ post.title }}</a></h1>
    <p>{{ post.text|linebreaksbr }}</p>
</div>

Ora aggiungiamo dei blocchi di codice ai nostri nuovi selettori. I selettori che iniziano con . indicano una classe. Online ci sono molti tutorial e spiegazioni sul CSS che possono aiutarti a comprendere il codice che stiamo per scrivere. Per ora, copia e incolla quanto segue nel tuo file mysite/static/css/blog.css:

.page-header {
    background-color: #ff9400;
    margin-top: 0;
    padding: 20px 20px 20px 40px;
}

.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active {
    color: #ffffff;
    font-size: 36pt;
    text-decoration: none;
}

.content {
    margin-left: 40px;
}

h1, h2, h3, h4 {
    font-family: 'Lobster', cursive;
}

.date {
    float: right;
    color: #828282;
}

.save {
    float: right;
}

.post-form textarea, .post-form input {
    width: 100%;
}

.top-menu, .top-menu:hover, .top-menu:visited {
    color: #ffffff;
    float: right;
    font-size: 26pt;
    margin-right: 20px;
}

.post {
    margin-bottom: 70px;
}

.post h1 a, .post h1 a:visited {
    color: #000000;
}

Ora aggiungi all'esterno del codice HTML riguardante i posts all'interno del blog alcuni elementi con definizione di classi. Sostituisci questo:

{% for post in posts %}
    <div class="post">
        <p>published: {{ post.published_date }}</p>
        <h1><a href="">{{ post.title }}</a></h1>
        <p>{{ post.text|linebreaksbr }}</p>
    </div>
{% endfor %}

nel file blog/templates/blog/post_list.html con quanto segue:

<div class="content container">
    <div class="row">
        <div class="col-md-8">
            {% for post in posts %}
                <div class="post">
                    <div class="date">
                        {{ post.published_date }}
                    </div>
                    <h1><a href="">{{ post.title }}</a></h1>
                    <p>{{ post.text|linebreaksbr }}</p>
                </div>
            {% endfor %}
        </div>
    </div>
</div>

Salva entrambi i file e ricarica la pagina web.

inparando django

Woohoo! È fantastico, vero? Il codice che abbiamo appena inserito non è poi così difficile da comprendere, dovresti riuscire a capirne la maggior parte semplicemente leggendolo.

Non farti spaventare, sperimenta con i CSS e prova a cambiare alcune cose. Se rompi qualcosa, non ti preoccupare, puoi sempre farlo tornare come era prima!

Compito per casa post-workshop: ti consigliamo caldamente di seguire il corso su HTML & CSS di Codeacademy. Così potrai imparare tutto ciò di cui hai bisogno per rendere i tuoi siti web più belli sfruttando il CSS.

Pronta per il prossimo capitolo?! :)

Estendere il template

Un'altra cosa bella di Django è l'estensione del template. Cosa significa? Significa che puoi usare le stesse parti del tuo HTML per pagine diverse del tuo sito.

Così non hai bisogno di ripetere le stesse informazioni/layout in ogni file. E se vuoi cambiare qualcosa, non devi cambiarlo in ogni templates, ma soltanto una volta!

Crea un template di base

Un template base è il template più semplice. Lo puoi estendere su ogni pagina del tuo sito.

Creiamo un file base.html in blog/templates/blog/:

 blog         
└───templates
    └───blog
            base.html
            post_list.html

Poi aprilo e copia tutto da post_list.html e incollalo sul file base.html, così:

{% load staticfiles %}
<html>
    <head>
        <title>My blog</title>
        <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS">        
        <link href='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    </head>
    <body>
        <div class="page-header">
            <h1><a href="/">My Blog</a></h1>
        </div>

        <div class="content container">
            <div class="row">
                <div class="col-md-8">
                {% for post in posts %}
                    <div class="post">
                        <div class="date">
                            {{ post.published_date }}
                        </div>
                        <h1><a href="">{{ post.title }}</a></h1>
                        <p>{{ post.text|linebreaksbr }}</p>
                    </div>
                {% endfor %}
                </div>
            </div>
        </div>
    </body>
</html>

Poi nel base.html, rimpiazza tutto il tuo <body> (tutto quello che si trova tra <body> e </body>) con questo:

<body>
    <div class="page-header">
        <h1><a href="/">My Blog</a></h1>
    </div>
    <div class="content container">
        <div class="row">
            <div class="col-md-8">
            {% block content %}
            {% endblock %}
            </div>
        </div>
    </div>
</body>

Abbiamo praticamente rimpiazzato tutto quello tra {% for post in posts %}{% endfor %} con:

{% block content %}
{% endblock %}

Che cosa significa? Che hai appena creato un blocco, ovvero un tag di template che ti permette di inserire l'HTML presente in questo blocco all'interno di altri template che estendono base.html. Ti mostreremo come farlo tra un attimo.

Ora salvalo, e apri il tuo blog/templates/blog/post_list.html di nuovo. Cancella tutto quello che non è all'interno del body e poi cancella anche <div class="page-header"></div>, in modo che il file appaia così:

{% for post in posts %}
    <div class="post">
        <div class="date">
            {{ post.published_date }}
        </div>
        <h1><a href="">{{ post.title }}</a></h1>
        <p>{{ post.text|linebreaksbr }}</p>
    </div>
{% endfor %}

Ed ora aggiungi questa riga all'inizio del file:

{% extends 'blog/base.html' %}

Significa che stiamo estendendo il template base.html in post_list.html. Rimane solo una cosa da fare: metti tutto (tranne la riga che abbiamo appena aggiunto) tra {% block content %} e {% endblock %}. Come questo:

{% extends 'blog/base.html' %}

{% block content %}
    {% for post in posts %}
        <div class="post">
            <div class="date">
                {{ post.published_date }}
            </div>
            <h1><a href="">{{ post.title }}</a></h1>
            <p>{{ post.text|linebreaksbr }}</p>
        </div>
    {% endfor %}
{% endblock %}

È tutto! Controlla se il tuo sito sta ancora funzionando correttamente :)

Se hai un errore TemplateDoesNotExists che dice che non c'è un file blog/base.html e hai runserver in esecuzione nella console, prova a fermarlo (premendo Ctrl+C - I tasti Control e C insieme) e riavvialo mettendo in esecuzione il comando python manage.py runserver.

Estendi la tua applicazione

Abbiamo completato i passi necessari per la creazione del nostro sito: sappiamo come scrivere un modello, una url, una view ed un template. Sappiamo anche come far diventare carino il nostro sito.

Ora di far pratica!

La prima cosa di cui abbiamo bisogno nel nostro blog è, ovviamente, una pagina per rendere visibile un post, vero?

Abbiamo già un modello dei Post, quindi non abbiamo bisogno di aggiungere niente in models.py.

Creare un link di template verso la pagina di dettaglio di un post

Cominceremo aggiungendo un link all'interno del file blog/templates/blog/post_list.html. Per ora dovrebbe avere questo aspetto:

{% extends 'blog/base.html' %}

{% block content %}
    {% for post in posts %}
        <div class="post">
            <div class="date">
                {{ post.published_date }}
            </div>
            <h1><a href="">{{ post.title }}</a></h1>
            <p>{{ post.text|linebreaksbr }}</p>
        </div>
    {% endfor %}
{% endblock content %}

Vogliamo creare un link che dal titolo di un post facente parte dell'elenco di articoli porti alla pagina di dettaglio. Cambiamo <h1><a href="">{{ post.title }}</a></h1> così che linki alla pagina di dettaglio del post:

<h1><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1>

È arrivata l'ora di spiegare il misterioso {% url 'post_detail' pk=post.pk %}. Come avrai capito, il simbolo {% %} significa che stiamo usando i tag del template di Django. Questa volta ne useremo uno che creerà una URL per noi!

blog.views.post_detail è un percorso per arrivare alla post_detail view che vogliamo creare. Nota bene: blog è il nome della nostra applicazione (la directory blog), views viene dal nome del file views.py e l'ultima cosa - post_detail - è il nome della view.

Adesso quando andremo all'indirizzo: http://127.0.0.1:8000/ avremo un errore (come sapevamo, dal momento che non abbiamo una URL oppure una view per post_detail). Avrà questo aspetto:

Crea una URL per i dettagli di un post

Creiamo una URL in urls.py per il nostro post_detail view!

Vogliamo che il nostro primo post venga visualizzato a questo URL http://127.0.0.1:8000/post/1/

Facciamo sì che l'URL nel file blog/urls.py punti Django ad una view chiamata post_detail, che mostrerà un intero post. Aggiungi la riga path('post/<int:pk>/', views.post_detail, name='post_detail'), al file blog/urls.py. Il file dovrebbe assomigliare a questo:

from django.conf.urls import path
from . import views

urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('post/<int:pk>/', views.post_detail, name='post_detail'),
]

Questa parte ^post/(<int:pk> sembra spaventosa, ma non preoccuparti - te la spiegheremo: - inizia ancora con ^ -- "l'inizio" - post/ semplicemente significa che dopo l'inizio, l'URL dovrebbe contenere la parola post e /. Fin qui tutto bene. - (<int:pk> - questa parte è più complicata. Significa che Django prenderà tutto quello che hai messo qui e lo trasferirà ad una view come variabile denominata pk[0-9] ci dice anche che la variabile può essere solo un numero, non una lettera (quindi tutto tra 0 e 9). + significa che ci devono essere una o più cifre. Quindi qualcosa di simile a http://127.0.0.1:8000/post// non è valido, ma http://127.0.0.1:8000/post/1234567890/ è perfetto! - / Quindi ci serve / di nuovo - $ - "fine"!

Ciò significa che se digiti http://127.0.0.1:8000/post/5/ nel tuo browser, Django capirà che stai cercando una view chiamata post_detail e trasferirà l'informazione che pk è uguale a 5 a quella view.

pk è un diminutivo di primary key. Questo nome viene frequentemente utilizzato nei progetti Django. Ma puoi chiamare la tua variabile come vuoi (ricorda: minuscole e _ invece degli spazi!). Per esempio invece di (<int:pk>) potremmo avere la variabile post_idquindi questo pezzettino dovrebbe assomigliare a: (<post_id>[0-9]+).

Ok, abbiamo aggiunto un nuovo schema di URL a blog/urls.py! Aggiorniamo la pagina: http://127.0.0.1:8000/ Boom! Ancora un altro errore! Come previsto!

Ti ricordi di quale è il prossimo passo? Ma certo: aggiungere una view!

Aggiungi una view del post

Questa volta alla nostra view viene data un altro parametro pk. La nostra view deve prenderlo, vero? Quindi definiremo la nostra funzione come def post_detail(request, pk):. Dobbiamo utilizzare esattamente lo stesso nome che abbiamo specificato in urls (pk). Omettere questa variabile è sbagliato e genererà un errore!

Ora, noi vogliamo ottenere un unico post. Per farlo possiamo utilizzare le queryset così:

Post.objects.get(pk=pk)

Ma questo codice presenta un problema. Se non c'è Post con primary key (pk) otterremo un errore bruttissimo!

Noi non lo vogliamo! Ma, senza dubbio, Django ha qualcosa che si occuperà del problema per noi: get_object_or_404. Nel caso in cui non ci sia Post con la data pk mostrerà una pagina molto più carina (chiamata Page Not Found 404).

La buona notizia è che in realtà puoi creare la tua pagina Page not found modificarla come vuoi e darle un bell'aspetto. Ma non è importantissimo in questo momento, quindi salteremo questa parte.

Ok, è arrivata l'ora di aggiungere una view al nostro file views.py!

Dovremo aprire blog/views.py ed aggiungere il seguente codice:

from django.shortcuts import render, get_object_or_404

Vicino ad altre righe from ed alla fine del file aggiungeremo la nostra view:

    def post_detail(request, pk):
        post = get_object_or_404(Post, pk=pk)
        return render(request, 'blog/post_detail.html', {'post': post})

Si, è giunta l'ora di aggiornare la pagina: http://127.0.0.1:8000/

inpara django

Ha funzionato! Ma cosa succede se clicchi su un link nel titolo del post?

Oh no! Un altro errore! Ma sappiamo già come occuparcene, giusto? Dobbiamo aggiungere un template!

Crea un template per il post detail

Creeremo un file in blog/templates/blog chiamato post_detail.html.

Il risultato somiglierà a questo:

{% extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.published_date %}
            <div class="date">
                {{ post.published_date }}
            </div>
        {% endif %}
        <h1>{{ post.title }}</h1>
        <p>{{ post.text|linebreaksbr }}</p>
    </div>
{% endblock %}

Stiamo estendendo ancora una volta il template di base. base.html. Nel blocco content vogliamo mostrare una published_date del post (se esiste), un titolo ed il testo. Ma dovremmo discutere di alcune cose importanti, vero?

{% if ... %} ... {% endif %} è un tag di template che possiamo utilizzare quando vogliamo controllare qualcosa (ricordi if ... else .. dal capitolo Introduzione a Python?). In questo caso vogliamo controllare che la published_date di un post non sia vuota.

Ok, possiamo aggiornare la nostra pagina e vedere se Page not found non c'è più.

inpara django

Si! Ha funzionato!

 

I form di Django

Infine vogliamo creare un bel modo per poter aggiungere e cambiare in nostri blog posts. Django adminè bello, ma è alquanto difficile da personalizzare e rendere carino. Con i forms avremo il potere assoluto sull'aspetto della nostra pagina web-possiamo fare praticamente qualsiasi cosa vogliamo!

La bella cosa dei Django forms è che possiamo sia inventare un nuovo form da zero che creare un ModelForm che salverà il risultato del form sul nostro modello.

Questo è esattamente quello che stiamo per fare: stiamo per creare un form per il nostro modello dei Post.

Come ogni parte importante di Django, i forms hanno il proprio file: forms.py.

Dobbiamo creare un file con questo nome all'interno della cartella blog.

blog
   └── forms.py

OK, apriamo questo file e inseriamo:

from django import forms

from .models import Post

class PostForm(forms.ModelForm):

    class Meta:
        model = Post
        fields = ('title', 'text',)

Dobbiamo importare prima di tutto i Django Forms (from django import forms) e, ovviamente, il nostro Post model (from .models import Post).

PostForm, come probabilmente hai intuito, è il nome del nostro form. Dobbiamo ora dire a Django che questa form é una ModelForm (così Django farà qualche magia per noi)- forms.ModelForm è il comando per farlo.

Successivamente, abbiamo class Meta, con cui diciamo a Django quale model utilizzare per creare questo form (model = Post).

Finalmente possiamo indicare uno o più campi che il nostro form deve avere. In questo caso vogliamo che solamente title e text siano visibili -author è la persona attualmente connessa (tu!) e created_date dovrebbe generarsi da sola ogni volta che creiamo un post (cioè nel nostro programma), giusto?

E questo è tutto! Tutto quello che dobbiamo fare ora é usare il form nella nostra view e visualizzarlo nel template.

Ricapitolando, creeremo: link che punti alla pagina, una URL, una view e un model.

È tempo di aprire blog/templates/blog/base.html. Aggiungeremo un link nel div chiamato page-header:

<a href="{% url 'post_new' %}" class="top-menu"><i class="fas fa-plus"></i></a>

Nota che vogliamo chiamare la nostra nuova view post_new.

Dopo aver aggiunto quanto detto, il tuo file html dovrebbe essere simile a questo:

{% load staticfiles %}
<html>
    <head>
        <title>My blog</title>
        <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css">
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css">
        <link href='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    </head>
    <body>
        <div class="page-header">
            <a href="{% url 'post_new' %}" class="top-menu"><i class="fas fa-plus"></i></a>
            <h1><a href="/">My Blog</a></h1>
        </div>
        <div class="content container">
            <div class="row">
                <div class="col-md-8">
                    {% block content %}
                    {% endblock %}
                </div>
            </div>
        </div>
    </body>
</html>

Dopo aver salvato e aggiornato la pagina http://127.0.0.1:8000 vedrai ovviamente un errore familiare NoReverseMatch, giusto?

URL

Apri il file blog/urls.py e aggiungi:

    path('post/new/', views.post_new, name='post_new'),

Il risultato finale sarà:

from django.conf.urls import path
from . import views

urlpatterns = [
    path('', views.post_list, name='post_list'),
    apth('post/<int:pk>/', views.post_detail, name='post_detail'),
    path('post/new/', views.post_new, name='post_new'),
]

Dopo aver aggiornato il sito, vedremo un AttributeError dal momento che non abbiamo ancora creato post_new. Aggiungiamolo adesso.

post_new view

Apri il file blog/views.py e aggiungi quanto segue con il resto delle importazioni from:

from .forms import PostForm

e la nostra view:

def post_new(request):
    form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

Per creare un nuovo Post form, dobbiamo chiamare il metodo PostForm() e passarlo nel nostro template. Torneremo poi sulla view, ma per ora creiamo un veloce template per il nostro form.

Template

All'interno della cartella blog/templates/blog dobbiamo creare il file post_edit.html. Per far si che il nostro form funzioni abbiamo bisogno di diverse cose:

  • dobbiamo rendere il form visibile. Per farlo possiamo usare semplicemente {{ form.as_p }}.
  • le righe scritte sopra hanno bisogno di 'essere avvolte' da un HTML tag: <form method="POST">...</form>
  • ci serve un Save pulsante. Possiamo fare ciò con HTML button: <button type="submit">Save</button>
  • infine, subito dopo l'apertura del tag <form ...>, dobbiamo aggiungere {% csrf_token %}. Questo passaggio è molto importante dal momento che rende il nostro form sicuro! Django si lamenterà se ti dimentichi di inserire questa parte e provi comunque a salvare ciò che è contenuto nel form:

OK, il tuo HTML post_edit.html dovrebbe apparire così:

{% extends 'blog/base.html' %}

{% block content %}
    <h1>New post</h1>
    <form method="POST" class="post-form">{% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="save btn btn-default">Save</button>
    </form>
{% endblock %}

Ora aggiorna la pagina! Yeah! Puoi ora visualizzare il tuo form!

inpara django

Ma, aspetta un momento! Se provi a scrivere qualcosa in title e text e cerchi di salvare ciò che hai scritto, che cosa succede?

Niente! Siamo di nuovo sulla stessa pagina di prima e il nostro testo é sparito...e non compare nessun nuovo post. Che cosa abbiamo sbagliato?

La risposta è: nulla. Dobbiamo solo fare un po' di lavoro in più nella nostra view.

Salvare il form

Apri blog/views.py di nuovo. Attualmente tutto ciò che abbiamo nella view post_new é:

def post_new(request):
    form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

Quando inviamo il form, veniamo riportati alla stessa view, ma questa volta abbiamo più dati in request, in particolare in request.POST (il nome non ha nulla a che vedere con un blog "post", bensì con l'inglese "posting", ovvero inviare, in questo caso dati). Ti ricordi che nel nostro file HTML il nostro <form> aveva la variabile method="POST"? Per cui ora, tutto quello che l'utente ha inserito nel form è disponibile in method="POST". Non è necessario rinominare POST in nessuna altra maniera (l'unico altro valore valido per method è GET, ma al momento non abbiamo abbastanza tempo per spiegare la differenza).

Per cui nella nostra view abbiamo due diverse situazioni da gestire. Prima: quando accediamo alla pagina per la prima volta e vogliamo un form che sia vuoto. Seconda: quando torniamo alla view con tutti i dati appena inseriti nel form. Per cui dobbiamo aggiungere una condizione(useremo if).

if request.method == "POST":
    [...]
else:
    form = PostForm()

È ora di completare i puntini [...]. Se il method è POST allora vogliamo costruire il nostro PostForm con i dati appena inseriti dall'utente, giusto? Raggiungeremo questo risultato con:

form = PostForm(request.POST)

Facile! Come prossima cosa dobbiamo controllare se il form è corretto (per cui che tutti i campi necessari siano stati impostati e che non ci siano valori sbagliati). Possiamo fare questo con form.is_valid().

Se il form viene ritenuto valido verrà salvato!

if form.is_valid():
    post = form.save(commit=False)
    post.author = request.user
    post.published_date = timezone.now()
    post.save()

In pratica, ci sono due cose da fare: salviamo il form con form.save e aggiungiamo un autore (dal momento che non c'era nessun campo autore author nel form PostForm e questo campo non può essere lasciato bianco!). commit=False significa che non vogliamo salvare Post model per il momento-vogliamo prima assicurarci di aggiungere un autore. Per la maggior parte del tempo userai form.save(), senza commit=False, ma in questo caso abbiamo bisogno di questa extra specificazione. post.save() salverà le modifiche (aggiunta di autore) e il nuovo post del tuo blog è stato finalmente creato!

Infine, non sarebbe fantastico se potessimo immediatamente essere indirizzati alla pagina post_detaildel nuovo blog post appena creato? Per fare ciò dobbiamo importare:

from django.shortcuts import redirect

Aggiungilo all'inizio del file. E ora possiamo dire: vai alla pagina post_detail per il post appena creato.

return redirect('post_detail', pk=post.pk)

post_detail é il nome della view che vogliamo visitare. Ti ricordi che questa view ha bisogno della variabile pk? Per passarla alla nostre views utilizziamo pk=post.pk, dove post è il post appena creato!

Ok, abbiamo parlato abbastanza ora e forse sei curioso/a di vedere l'aspetto della nostra view, giusto?

def post_new(request):
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

Vediamo se funziona. Vai sulla pagina http://127.0.0.1:8000/post/new/, aggiungi un title e un text, salvalo... e voilà! Il tuo nuovo post è stato aggiunto e noi siamo stati reindirizzati automaticamente alla pagina post_detail !

Forse avrai notato che stiamo impostando una data di pubblicazione prima di salvare il post. Più tardi introdurremo l'uso del publish button in Django Girls Tutorial: Extensions.

Fantastico!

Validazione del Form

E adesso ti dimostreremo quanto siano belli i form di Django. Sappiamo che un post ha bisogno di title e text. Nel nostro Post model non abbiamo detto (al contrario di quello che abbiamo fatto per published_date) che questi campi non sono obbligatori, per cui Django si aspetta che vengano impostati.

Prova a salvare il form senza title e text. Indovina che cosa accade!

impara django

Django si sta prendendo cura di controllare che tutti i campi nel nostro form siano corretti. Non è fantastico?

Dato che poco fa stavamo usando l'interfaccia di Django admin, Django pensa che siamo ancora connessi. Ci sono alcune situazioni che potrebbero portarci a fare un log out(chiudere il browser, riavviare il DB etc.). Se ti trovi nella situazione di avere errori, quando crei un post, relativi alla mancanza di un utente, vai alla admin page http://127.0.0.1:8000/admin ed effettua il log in di nuovo. Questo risolverà temporaneamente il problema. C'è una correzione permanente che ti aspetta nella sezione degli esercizi extra alla fine del tutorial principale Compiti: aggiungi sicurezza al tuo sito web!.

Modifica il form

Ora sappiamo come aggiungere un form. Ma cosa succede se ne vogliamo cambiare uno esistente? È un processo abbastanza simile a quelli che abbiamo appena fatto. Creiamo alcune cose importanti rapidamente (se non capisci qualcosa, chiedi aiuto al tuo coach o guarda i capitoli precedenti, dal momento che abbiamo coperto tutti questi passaggi precedentemente).

Apri blog/templates/blog/post_detail.html e aggiungi:

<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><i class="fas fa-pencil-alt"></i></a>

per cui il tuo template sarà così:

{% extends 'blog/base.html' %}

{% block content %}
    <div class="post">
        {% if post.published_date %}
            <div class="date">
                {{ post.published_date }}
            </div>
        {% endif %}
        <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><i class="fas fa-pencil-alt"></i></a>
        <h1>{{ post.title }}</h1>
        <p>{{ post.text|linebreaksbr }}</p>
    </div>
{% endblock %}

In blog/urls.py aggiugi:

    path('post/<int:pk>/edit/$', views.post_edit, name='post_edit'),

Riutilizzeremo il model blog/templates/blog/post_edit.html, quindi l'ultima cosa che manca è una view.

Apriamo blog/views.py e aggiungiamo alla fine del file:

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == "POST":
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.published_date = timezone.now()
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = PostForm(instance=post)
    return render(request, 'blog/post_edit.html', {'form': form})

Questo sembra quasi esattamente la view post_new, giusto? Ma non del tutto. Prima cosa: si passa un parametro supplementare pk dall'URL. Dopo di che: prendiamo il modello Post che vogliamo modificare con get_object_or_404(Post, pk=pk) e in seguito, quando creeremo un form, passeremo questo post come instance, sia quando salviamo il form:

form = PostForm(request.POST, instance=post)

e quando abbiamo appena aperto un form con questo post da modificare:

form = PostForm(instance=post)

Ok, testiamo se funziona! Andiamo alla pagina post_detail. Dovrebbe esserci un pulsante modifica nell'angolo superiore destro:

impara django

Quando ci clicchi, vedrai il modulo con i nostri post del blog:

impara django

Sentiti libero di cambiare il titolo o il testo e salva le modifiche!

Complimenti! La tua application è sempre più completa!

Se ti servono altre informazioni sui forms di Django dovresti leggere la documentazione: https://docs.djangoproject.com/en/1.8/topics/forms/

Sicurezza

Riuscire a creare nuovi post semplicemente cliccando su un link è bellissimo! Ma, al momento, chiunque visiti il tuo sito potrebbe pubblicare un nuovo post nel tuo blog e probabilmente non vuoi che ciò accada. Facciamo in modo che questo tasto sia visibile solo per te e non per altri.

Vai al tuo blog/templates/blog/base.html e trova il page-header div con il tag di tipo anchor che hai messo prima. Dovrebbe apparire così:

<a href="{% url 'post_new' %}" class="top-menu"><i class="fas fa-plus"></i></a>

Vogliamo aggiungere qui un altro tag del tipo {% if %} che farà comparire il link solo per gli utenti connessi come admin. Per ora, solo tu! Cambia il tag <a> in modo che risulti così:

{% if user.is_authenticated %}
    <a href="{% url 'post_new' %}" class="top-menu"><i class="fas fa-plus"></i></a>
{% endif %}

Adding security to your website

You might have noticed that you didn't have to use your password, apart from back when we used the admin interface. You might also have noticed that this means that anyone can add or edit posts in your blog. I don't know about you, but I don't want just anyone to post on my blog. So let's do something about it.

Authorizing add/edit of posts

First let's make things secure. We will protect our post_newpost_edit  views so that only logged-in users can access them. Django ships with some nice helpers for doing that, called decorators. Don't worry about the technicalities now; you can read up on these later. The decorator we want to use is shipped in Django in the module django.contrib.auth.decorators and is called login_required.

So edit your blog/views.py and add these lines at the top along with the rest of the imports:

from django.contrib.auth.decorators import login_required

Then add a line before each of the post_newpost_edit  views (decorating them) like the following:

@login_required
def post_new(request):
    [...]

That's it! Now try to access http://localhost:8000/post/new/. Notice the difference?

If you just got the empty form, you are probably still logged in from the chapter on the admin-interface. Go to http://localhost:8000/admin/logout/ to log out, then go to http://localhost:8000/post/new again.

You should get one of our beloved errors. This one is quite interesting, actually: the decorator we added will redirect you to the login page, but since that's not yet available, it raises a "Page not found (404)".

Don't forget to add the decorator from above to post_edit.

Hooray, we've reached part of our goal!! Now other people can't create posts on our blog anymore. Unfortunately we can't create posts anymore too. So let's fix that next.

Log in users

We could now try to do lots of magical stuff to implement users and passwords and authentication, but doing this correctly is rather complicated. As Django is "batteries included", someone has done the hard work for us, so we will make further use of the authentication tools provided.

In your mysite/urls.py add a url path('accounts/login/', views.LoginView.as_view(), name='login'). So the file should now look similar to this:

from django.urls import path, include
from django.contrib import admin

from django.contrib.auth import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/login/', views.LoginView.as_view(), name='login'),
    path('', include('blog.urls')),
]

Then we need a template for the login page, so create a directory blog/templates/registration and a file inside named login.html:

{% extends "blog/base.html" %}

{% block content %}
    {% if form.errors %}
        <p>Your username and password didn't match. Please try again.</p>
    {% endif %}

    <form method="post" action="{% url 'login' %}">
    {% csrf_token %}
        <table>
        <tr>
            <td>{{ form.username.label_tag }}</td>
            <td>{{ form.username }}</td>
        </tr>
        <tr>
            <td>{{ form.password.label_tag }}</td>
            <td>{{ form.password }}</td>
        </tr>
        </table>

        <input type="submit" value="login" />
        <input type="hidden" name="next" value="{{ next }}" />
    </form>
{% endblock %}

You will see that this also makes use of our base template for the overall look and feel of your blog.

The nice thing here is that this just worksTM. We don't have to deal with handling of the form submission nor with passwords and securing them. Only more thing is left to do. We should add a setting to mysite/settings.py:

LOGIN_REDIRECT_URL = '/'

so that when the login page is accessed directly, it will redirect a successful login to the top-level index (the homepage of our blog).

Improving the layout

We already set things up so that only authorized users (i.e. us) see the buttons for adding and editing posts. Now we want to make sure a login button appears for everybody else.

We will add a login button that looks like this:

    <a href="{% url 'login' %}" class="top-menu"><i class="fas fa-lock"></i></a>

For this we need to edit the templates, so let's open up blog/templates/blog/base.html and change it so the part between the <body> tags looks like this:

<body>
    <div class="page-header">
        {% if user.is_authenticated %}
            <a href="{% url 'post_new' %}" class="top-menu"><i class="fas fa-plus"></i></a>
        {% else %}
            <a href="{% url 'login' %}" class="top-menu"><i class="fas fa-lock"></i></a>
        {% endif %}
        <h1><a href="/">My Blog</a></h1>
    </div>
    <div class="content container">
        <div class="row">
            <div class="col-md-8">
            {% block content %}
            {% endblock %}
            </div>
        </div>
    </div>
</body>

You might recognize the pattern here. There is an if-condition in the template that checks for authenticated users to show the add and edit buttons. Otherwise it shows a login button.

More on authenticated users

Let's add some sugar to our templates while we're at it. First we will add some details to show when we are logged in. Edit blog/templates/blog/base.html like this:

<div class="page-header">
    {% if user.is_authenticated %}
        <a href="{% url 'post_new' %}" class="top-menu"><i class="fas fa-lock"></i></a>
        <p class="top-menu">Hello {{ user.username }} <small>(<a href="{% url 'logout' %}">Log out</a>)</small></p>
    {% else %}
        <a href="{% url 'login' %}" class="top-menu"><i class="fas fa-lock"></i></a>
    {% endif %}
    <h1><a href="/">My Blog</a></h1>
</div>

This adds a nice "Hello <username>" to remind us who we are logged in as, and that we are authenticated. Also, this adds a link to log out of the blog -- but as you might notice this isn't working yet. Let's fix it!

We decided to rely on Django to handle login, so let's see if Django can also handle logout for us. Check https://docs.djangoproject.com/en/2.0/topics/auth/default/ and see if you find something.

Done reading? By now you may be thinking about adding a URL in mysite/urls.py pointing to Django's logout view (i.e. django.contrib.auth.views.logout), like this:

from django.urls import path, include
from django.contrib import admin

from django.contrib.auth import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/login/', views.LoginView.as_view(), name='login'),
    path('accounts/logout/', views.LogoutView.as_view(next_page='/'), name='logout'),
    path('', include('blog.urls')),
]

That's it! If you followed all of the above up to this point (and did the homework), you now have a blog where you

  • need a username and password to log in,
  • need to be logged in to add, edit, publish or delete posts,
  • and can log out again.

ALBATEK