Django Tutorial Part 7: Sessions framework

Questo tutorial estende il nostro sito LocalLibrary, aggiungendo un contatore di visite session-based alla home page. Questo è un esempio relativamente semplice, ma mostra come si può usare il session framework per fornire comportamento persistente per utenti anonimi nei tuoi siti.

Prerequisiti: Completa tutti gli argomenti dei tutorial precedenti, compreso Django Tutorial Part 6: Generic list and detail views
Obiettivo: Capire come vengono utilizzate le sessioni.

Panoramica

Il sito LocalLibrary che abbiamo creato nei precedenti tutorial permette agli utenti di navigare tra i libri e gli autori nel catalogo. Anche se il contenuto viene generato dinamicamente dal database, ogni utente essenzialmente avrà accesso alle stesse pagine e e gli stessi tipi di informazione quando utilizzano il sito.

In una biblioteca "reale" potresti desiderare di fornire agli utenti individuali una esperienza customizzata, basata sul loro precedente utilizzo del sito, preferenze, ecc. Per esempio, potresti nascondere messaggi di avviso di cui gli utenti hanno già preso conoscenza la prossima volta che essi visitano il sito, o archiviare e rispettare le loro preferenze (ad esempio, il numero di risultati di ricerca che vogliono mostrato su ogni pagina). 

Il session framework ti consente di implementare questo tipo di comportamento, permettendoti di memorizzare e recuperare dati arbitrari su una base di visitstore per sito (per-site-visitor). 

Cosa sono le sessioni?

Tutte le comunicazioni tra browser web e i server avvengono attraverso il prootocollo HTTP, che è stateless. Il fatto che il protocollo sia stateless significa che i messagggi tra il client e il server sono completamente indipendenti da ciascuno degli altri— non esiste la nozione di "sequenza" o comportamento basato sui precedenti messaggi. Di conseguenza, se vuoi avere un sito che tenga traccia delle relazioni che sono in attive con un client, hai bisogno di implementarlo tu stesso.

Le sessioni sono il meccanismo utilizzato da Django (e dalla maggior parte dell'Internet) per tenere traccia dello "stato" tra il sito e un particolare browser. Le sessioni ti consentono di memorizzare dati arbitrari per browser, e avere questi dati disponibili per il sito ogni volta che il browser si connette. Item individuali di dati associati con la sessione sono quindi referenziati con una "key", la quale è utilizzata sia per rchiviare che per recuperare i dati.

Django utilizza un cookie contenente uno speciale session id per identificare ciascun browser e la sua sessione associata col sito. I dati della sessione effettiva sono archiviati nel database del sito di default (questo è più sicuro del memorizzare i dati in un cookie, dove sono più vulnerabili a utenti malevoli). Si può configurare Django per memorizzare i dati della sessione in altre posizioni (nella cache, nei file, nei "secure" cookie), ma la posizione di default è una opzione buona e relativamente sicura.

Abilitare le sessioni

Le sessioni sono state abilitate automaticamente quando abbiamo creato lo scheletro del sito web (nel tutorial 2).

La configurazione è imnpostata nelle sezioni INSTALLED_APPS e MIDDLEWARE del file di progetto (locallibrary/locallibrary/settings.py), come mostrato qui sotto:

INSTALLED_APPS = [
    ...
    'django.contrib.sessions',
    ....

MIDDLEWARE = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    ....

Utilizzo delle sessioni

Si può accedere all'attributo session nell view dal parametro request (una HttpRequest passata dentro come primo argomento alla view). Questo attributo sessione rappresenta la connessione specifica con l'utente attuale (o per essere più precisi, la connessione al browser attuale, come identificato dal session id nel cookie del browser per questo sito).

L'attributo session è un oggetto simile a un dizionario (dictionary-like) che puoi leggere e scrivere quante volte vuoi nella tua view, modificandolo come desiderato. Si possono effettuare tutte le normali operazioni dei dictionary, inclusa la cancellazione di tutti i dati, testare se una chiave è presente, ciclare sui dati, ecc. Il più delle volte userete solo l'API standard "dictionary" per ottenere valori e impostare valori.

I frammenti di codice sotto mostrano come si può ottenere, impostare, e cancellare alcuni dati con la key "my_car", associata alla sessione corrente (browser). 

Nota: Una delle cose belle di Django è che non c'è bisogno di pensare ai meccanismi che legano la sessione alla tua attuale richiesta nella tua view. Se dovessimo usare i frammenti di codice qui sotto nella nostra view, sapremmo che l'informazione su my_car è associata solo al browser che ha inviato la richiesta corrente.

# Get a session value by its key (e.g. 'my_car'), raising a KeyError if the key is not present
my_car = request.session['my_car']

# Get a session value, setting a default if it is not present ('mini')
my_car = request.session.get('my_car', 'mini')

# Set a session value
request.session['my_car'] = 'mini'

# Delete a session value
del request.session['my_car']

L'API offre anche un certo numero di altri metodi che sono usati principalmente per gestire il cookie associato alla sessione. Per esampio, ci sono metodi per testare che i cookie sono supportati nel browser client, per impostare e controllare la data di scadenza del cookie, e per cancellare le sessioni scadute dal data store. Puoi trovare informazioni sulla API completa in How to use sessions (Django docs).

Salvare i dati di sessione

Di default, Django salva solamente il database di sessione e invia il session cookie al client quando la sessione è stata modificata (assegnata) ocancellata. Se si sta aggiornando qualche dato utilizzando la sua session key come mostrato nella precedente sezione, allora non devi preoccuparti di questo! Per esempio:

# This is detected as an update to the session, so session data is saved.
request.session['my_car'] = 'mini'

Se si stanno aggiornando alcune informazioni all'interno dei dati di sessione, allora Django non riconoscerà che hai fatto una modifica alla sessione e salva i dati (per esempio, se dovessi modificare i dati "wheels" all'interno dei tuoi dati "my_car", come mostrato sotto). In questo caso avrai bisogno di contrassegnare esplicitamente la sessione come modificata.

# Session object not directly modified, only data within the session. Session changes not saved!
request.session['my_car']['wheels'] = 'alloy'

# Set session as modified to force data updates/cookie to be saved.
request.session.modified = True

Nota: Si può modificare il comportamento in modo che il sito aggiorni il database/invii cookie su ciascuna request aggiungendo SESSION_SAVE_EVERY_REQUEST = True nelle tue impostazioni di progetto (locallibrary/locallibrary/settings.py).

Semplice esempio — ottenere il conteggio delle visite

Come esempio semplice del mondio reale, aggiorneremo la nostra biblioteca per dire all'utente attuale quante volte essi hanno visitato la home page della LocalLibrary

Apri /locallibrary/catalog/views.py, e effettua le modifiche mostrate in grassetto sotto. 

def index(request):
    ...

    num_authors = Author.objects.count()  # The 'all()' is implied by default.
    
    # Number of visits to this view, as counted in the session variable.
    num_visits = request.session.get('num_visits', 0)
    request.session['num_visits'] = num_visits + 1

    context = {
        'num_books': num_books,
        'num_instances': num_instances,
        'num_instances_available': num_instances_available,
        'num_authors': num_authors,
        'num_visits': num_visits,
    }
    
    # Render the HTML template index.html with the data in the context variable.
    return render(request, 'index.html', context=context)

Qui prima otteniamo il valore della session key 'num_visits', impostiamo il valore a 0 se esso non è stato precedentemente impostato. Ogni volta che viene ricevuta una richiesta, allora si incrementa il valore e lo si memorizza di nuovo nella sessione (per la prossima volta che l'utente visita la pagina). La variabile num_visits viene quindi passata al template nella nostra variabile context.

Nota: Potremmo anche verificare se i cookie sono anche supportati nel browser qui (vedi How to use sessions per esempi) o progettare la nostra UI in modo che non importa se i cookie sono supportati o meno.

Aggiungi la linea che trovi alla fine del blocco qui sotto al tuo template HTML principale (/locallibrary/catalog/templates/index.html) alla fine della sezione "Dynamic content" per mostrare la variabile context:

<h2>Dynamic content</h2>

<p>The library has the following record counts:</p>
<ul>
  <li><strong>Books:</strong> {{ num_books }}</li>
  <li><strong>Copies:</strong> {{ num_instances }}</li>
  <li><strong>Copies available:</strong> {{ num_instances_available }}</li>
  <li><strong>Authors:</strong> {{ num_authors }}</li>
</ul>

<p>You have visited this page {{ num_visits }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p>

Salva le modifiche e riavvia il server di test. Ogni volta che tu farai un refresh della pagina, il numero dovrebbe aggiornarsi.

Ora sai come è facile utilizzare per migliorare la tua interazione con utenti anonimi

Nei nostri prossimi articoli spiegheremo il framework per l'autenticazione ed autorizzazione (permessi), e ti mostreremo come supportare gli account user.

Vedi anche

In questo modulo