Oggetti di richiesta e risposta
Breve panoramica
Django usa oggetti di richiesta e risposta per passare lo stato nel sistema.
Quando è richiesta una pagina, Django crea un oggetto HttpRequest contenente i metadati relativi alla richiesta effettuata. Poi avviene il caricamento della view appropriata ed il passaggio dell'oggetto HttpRequest alla funzione corrispondente alla view, come primo argomento. Infine, ogni view è tenuta a fornire come risposta un oggetto HttpResponse.
Questo documento descrive le API relative agli oggetti HttpRequest e HttpResponse.
Oggetti HttpRequest
Attributi
Tutti gli attributi eccetto session sono utilizzabili in sola lettura.
- path
Una stringa che rappresenta il percorso completo della pagina richiesta, escludendo il nome del dominio.
Esempio: "/music/bands/the_beatles/"
- method
Una stringa che corrispondente al metodo HTTP usato nella richiesta. E' garantito che vengano utilizzate lettere maiuscole. Esempio:
if request.method == 'GET': fai_qualcosa() elif request.method == 'POST': fai_qualcosa_di_altro()
- GET
- Un oggetto "dictionary-like" contenente tutti i parametri HTTP GET che sono stati specificati. Vedi la documentazione seguente relativa a QueryDict.
- POST
Un oggetto "dictionary-like" contenente tutti i parametri HTTP POST che sono stati specificati. Vedi la documentazione seguente relativa a QueryDict.
E' possibile che una richiesta possa arrivare via POST pur essendo vuoto il dizionario POST -- se, ad esempio, un form viene inviato via HTTP POST ma non include dati. Perciò non dovresti usare if request.POST per prendere decisioni. Invece, puoi effettuare una verifica corretta tramite il metodo method.
Nota: l'attributo POST non include le informazioni sui file caricati tramite form. Per questo vedi la sezione FILES.
- REQUEST
Definito per comodità, è un oggetto "dictionary-like" in cui la ricerca dei parametri avviene prima usando l'attributo POST, poi usando GET. L'idea di implementare REQUEST è nata prendendo spunto da $_REQUEST di PHP.
Ad esempio, se GET = {"name": "john"} e POST = {"age": '34'}, REQUEST["name"] restituirebbe "john", e REQUEST["age"] restituirebbe "34".
E' vivamente consigliato l'utilizzo di GET e POST al posto di REQUEST, in quanto le prime due formule risultano più esplicite.
- COOKIES
- E' un dizionario contenente tutti i cookies. Le chiavi e valori sono stringhe.
- FILES
Un oggetto "dictionary-like" contenente le informazioni su tutti i file caricati dall'utente tramite form. Ogni chiave di FILES coincide con il valore di name ottenuto da <input type="file" name="" />. Ogni valore invece è un normale dizionario in cui compaiono tre chiavi:
- filename -- Il nome del file, come stringa.
- content-type -- Il tipo di contenuto del file.
- content -- Il contenuto del file.
Nota che l'attributo FILES conterrà dati solamente se il metodo della richiesta è di tipo POST e il tipo di contenuto specificato in <form> mediante enctype risulta essere multipart/form-data (enctype="multipart/form-data"). Diversamente FILES sarà un oggetto "dictionary-like" vuoto.
- META
E' un dizionario contenente tutti gli header HTTP disponibili. In genere la disponibilità degli header varia in funzione del client e del server; di seguito sono elencate alcune intestazioni HTTP a titolo di esempio:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT_ENCODING
- HTTP_ACCEPT_LANGUAGE
- HTTP_REFERER -- La pagina di provenienza, se esiste.
- HTTP_USER_AGENT -- La stringa di identificazione del browser che ha effettuato la richiesta.
- QUERY_STRING -- La stringa contenente i parametri, sottoforma di un'unica stringa non elaborata.
- REMOTE_ADDR -- L'indirizzo IP del client.
- REMOTE_HOST -- Il nome host del client.
- REQUEST_METHOD -- Una stringa come "GET" o "POST".
- SERVER_NAME -- Il nome host del server.
- SERVER_PORT -- La porta di comunicazione del server.
- user
Rappresenta l'utente attualmente loggato come oggetto django.contrib.auth.models.User. Se non sono disponibili le credenziali d'accesso dell'utente che ha effettuato la richiesta, user conterrà un'istanza di django.contrib.auth.models.AnonymousUser. Puoi diversificare le possibilità per questo tipo di utente rispetto agli utenti loggati usando is_anonymous() come nell'esempio:
if request.user.is_anonymous(): # Fai qualcosa per gli utenti anonimi. else: # Fai qualcosa per gli utenti autenticati.
user è disponibile soltanto se AuthenticationMiddleware è stato attivato per questa installazione di Django. Per ulteriori dettagli consulta Autenticazione nelle richieste Web.
- session
- E' un oggetto "dictionary-like" a cui si può accedere in lettura e scrittura con cui viene rappresentata la sessione corrente. L'oggetto session è disponibile solamente se nell'installazione di Django è attivo il supporto per le sessioni. Per i dettagli completi consulta la documentazione relativa alle sessioni.
- raw_post_data
- I dati grezzi di HTTP POST. Viene usato per elaborazioni avanzate. Nella maggior parte dei casi userai POST invece di raw_post_data.
Metodi
- __getitem__(key)
Restituisce il valore GET/POST per la chiave specificata (key), controllando prima POST poi GET. Solleva un'eccezione KeyError se la chiave non esiste.
Questo consente di accedere ad una istanza HttpRequest usando la sintassi con cui normalmente si accede ai dizionari. Ad esempio: request["foo"] restituisce True se "foo" è presente come chiave in request.POST o request.GET
- has_key()
- Restituisce True o False, indicando se la chiave specificata è presente in request.GET o in request.POST.
- get_full_path()
Restituisce il path, accodando la query string, se presente.
Ad esempio: "/music/bands/the_beatles/?print=true"
Oggetti QueryDict
Gli attributi GET e POST di un oggetto HttpRequest sono istanze di django.http.QueryDict. QueryDict è una classe "dictionary-like", cioè simile ad un dizionario, progettata per gestire molteplici valori per una stessa chiave. Ciò si rende necessario perché alcuni elementi relativi ai form HTML, in particolare <select multiple="multiple">, passano più valori per la stessa chiave.
Le istanze QueryDict sono immutabili, a meno che ne venga creata una copia con copy(). Ne segue che non puoi cambiare direttamente gli attributi di request.POST e request.GET.
Essendo QueryDict una classe derivata dagli oggetti dizionario, tutti i metodi standard propri dei dizionari vengono implementati, con le differenze elencate di seguito:
- __getitem__(key) -- Restituisce il valore corrispondente alla chiave fornita (key), o l'ultimo dei valori se la chiave è associata a più di un valore.
- __setitem__(key, value) -- Imposta la chiave specificata (key) al valore [value] (una lista Python il cui singolo elemento è value). Nota che questa funzione, come le altre funzioni sui dizionari che prevedano conseguenze "attive", può essere eseguita soltanto su QueryDict mutabili (quelli creati usando copy()).
- __contains__(key) -- Restituisce True se la chiave (key) è impostata. In questo modo è possibile, ad esempio, scrivere: if "foo" in request.GET.
- get(key, default) -- Usa la stessa logica adottata da __getitem__() restituendo un valore predefinito (default) se la chiave (key) non esiste.
- has_key(key)
- setdefault(key, default) -- equivalente al metodo setdefault() dei dizionari usuali, eccetto per l'utilizzo interno di __setitem__.
update(other_dict) -- Accetta un QueryDict o un normale dizionario. Si comporta come il metodo update() dei normali dizionari, salvo per il fatto di accodare gli elementi al dizionario corrente, invece di rimpiazzarli. Ad esempio:
>>> q = QueryDict('a=1') >>> q = q.copy() # lo rende mutabile >>> q.update({'a': '2'}) >>> q.getlist('a') ['1', '2'] >>> q['a'] # restituisce l'ultimo ['2']
items() -- Si comporta come il metodo items() dei normali dizionari, salvo per il fatto che viene usata la logica adottata da __getitem()__ di restituire l'ultimo valore. Ad esempio:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.items() [('a', '3')]
values() -- Si comporta come il metodo values() dei normali dizionari, salvo per il fatto che viene usata la logica di restituire l'ultimo valore adottata da __getitem()__. Ad esempio:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.values() ['3']
In aggiunta, QueryDict fornisce i seguenti metodi:
- copy() -- Restituisce una copia dell'oggetto generata usando copy.deepcopy() fornito dalla libreria standard di Pyhton. La copia sarà mutabile -- ovvero, i valori potranno essere modificati.
- getlist(key) -- Restituisce i dati assieme alla chiave (key), sottoforma di lista Python. Se la chiave non esiste viene restituita una lista vuota. Usando questo metodo è garantito che il risultato sia comunque una lista.
- setlist(key, list_) -- Imposta la chiave (key) al valore list_ (diversamente da __setitem__()).
- appendlist(key, item) -- Accoda un elemento (item) alla lista associata alla chiave (key).
- setlistdefault(key, default_list) -- Equivalente al metodo setdefault, fatto salvo che ammette una lista (default_list) invece di un singolo valore.
lists() -- funziona come items(), ma vengono inclusi tutti i valori, in forma di lista, per ogni elemento del dizionario. Ad esempio:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])]
- urlencode() -- Restituisce una stringa dei dati sottoforma di query-string. Ad esempio: "a=2&b=3&b=5".
Esempi
Questo è un esempio di form HTML e di come Django tratterebbe gli input:
<form action="/foo/bar/" method="post"> <input type="text" name="your_name" /> <select multiple="multiple" name="bands"> <option value="beatles">The Beatles</option> <option value="who">The Who</option> <option value="zombies">The Zombies</option> </select> <input type="submit" /> </form>
Se l'utente inserisce "John Smith" nel campo your_name e sceglie sia "The Beatles" che "The Zombies" dalla select box a scelta multipla, la richiesta si presenterebbe in questo modo:
>>> request.GET {} >>> request.POST {'your_name': ['John Smith'], 'bands': ['beatles', 'zombies']} >>> request.POST['your_name'] 'John Smith' >>> request.POST['bands'] 'zombies' >>> request.POST.getlist('bands') ['beatles', 'zombies'] >>> request.POST.get('your_name', 'Adrian') 'John Smith' >>> request.POST.get('nonexistent_field', 'Nowhere Man') 'Nowhere Man'
Note sull'implementazione
Al fine di ottimizzare l'utilizzo delle risorse disponibili, i valori degli attributi GET, POST, COOKIES, FILES, META, REQUEST, raw_post_data e user vengono caricati soltanto nel momento in cui ne è richiesto l'utilizzo da parte del codice.
Oggetti HttpResponse
Diversamente dagli oggetti HttpRequest, creati automaticamente da Django, gli oggetti HttpResponse sono una tua responsabilità. Devi prevedere che qualsiasi view che scrivi istanzi, popoli e restituisca un HttpResponse.
La classe HttpResponse si trova in django.http.HttpResponse.
Utilizzo
Passaggio di stringhe
La tipica situazione di utilizzo è il passaggio dei contenuti di una pagina, come stringa, al costruttore dell'oggetto HttpResponse:
>>> response = HttpResponse("Questo è il testo della pagina Web.") >>> response = HttpResponse("Soltanto testo, per cortesia.", mimetype="text/plain")
Se vuoi aggiungere contenuti in modo incrementale, puoi usare response come fosse un oggetto file:
>>> response = HttpResponse() >>> response.write("<p>Questo è il testo della pagina Web.</p>") >>> response.write("<p>Questo è un altro paragrafo.</p>")
Puoi inserire nuovi header o effettuare rimozioni usando la sintassi valida per i dizionari:
>>> response = HttpResponse() >>> response['X-DJANGO'] = "E' il migliore." >>> del response['X-PHP'] >>> response['X-DJANGO'] "E' il migliore."
Nota che del non solleva un KeyError se l'header non esiste.
Passaggio di iteratori
Invece di passare stringhe predefinite, ad HttpResponse puoi passare un iteratore. Se intendi utilizzare questa tecnica attieniti alle seguenti direttive:
- L'iteratore deve restituire stringhe.
- Se un oggetto HttpResponse è stato inizializzato con un iteratore come suo contenuto, non potrai usare le sue istanze come oggetti "file-like". Ciò solleverebbe un'eccezione.
Metodi
- __init__(content='', mimetype=DEFAULT_MIME_TYPE)
Istanzia un oggeto HttpResponse con il contenuto della pagina come stringa (content) e un tipo MIME (mimetype). Il tipo MIME predefinito, DEFAULT_MIME_TYPE è 'text/html'.
content può essere un iteratore o una stringa. Nel caso sia un iteratore, ci si aspetta che restituisca stringhe, che saranno in seguito unite e per diventare il contenuto della risposta.
- __setitem__(header, value)
- Imposta un valore per l'header specificato. E' richiesto che header e value siano stringhe.
- __delitem__(header)
- Rimuove l'header specificato. Se l'header è inesistente non vengono segnalati errori. Distingue lettere maiuscole da lettere minuscole.
- __getitem__(header)
- Restituisce il valore dell'header specificato. Distingue lettere maiuscole da lettere minuscole.
- has_header(header)
- Restituisce True o False sulla base dell'esistenza dell'header specificato. Non vi è distinzione tra lettere maiuscole e lettere minuscole.
- set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)
Imposta un cookie. I parametri sono gli stessi che si trovano nell'oggetto cookie Morsel nella libreria standard di Python.
- max_age specifica un numero di secondi, o None (impostazione predefinita) se è previsto che il cookie venga mantenuto per tutta la durata della sessione di navigazione dell'utente (chiusura del browser).
- expires specifica una stringa nel formato "Wdy, DD-Mon-YY HH:MM:SS GMT".
- Usa il parametro domain se vuoi impostare un cookie cross-domain. Ad esempio, domain=".lawrence.com" ha l'effetto di impostare un cookie leggibile dai domini www.lawrence.com, blogs.lawrence.com e calendars.lawrence.com. Non impostando il valore di domain il cookie sarebbe leggibile soltanto dal dominio che ne ha originato la creazione.
- delete_cookie(key)
- Elimina il cookie con la chiave specificata (key). Se la chiave è inesistente non vengono segnalati errori.
- content
- Restituisce il contenuto come stringa Python, eseguendo l'encoding Unicode se necessario. Nota che content è una proprietà, non un metodo, perciò usa r.content invece di r.content().
- write(content), flush() e tell()
- Questi metodi rendono un'istanza HttpResponse un oggetto file-like.
Sottoclassi di HttpResponse
Django include alcune sottoclassi di HttpResponse adatte a fornire differenti tipologie di risposte HTTP. Come per HttpResponse, queste sottoclassi si trovano in django.http.
- HttpResponseRedirect
- Il costruttore accetta un solo argomento -- il percorso di redirezione, come URL completamente specificato (ad esempio, 'http://www.yahoo.com/search/') o come URL assoluto senza dominio (ad esempio, '/search/'). Nota che il codice di stato HTTP restituito è 302.
- HttpResponsePermanentRedirect
- Funziona come HttpResponseRedirect, ma restituisce uno stato di redirezione permanente (codice HTTP 301) invece di un redirect con codice 302.
- HttpResponseNotModified
- Il costruttore non prevede alcun argomento. Usa questo tipo di risposta per indicare che una pagina non è stata modificata dall'ultima richiesta dell'utente.
- HttpResponseNotFound
- Si comporta come HttpResponse ma usa il codice di stato 404.
- HttpResponseForbidden
- Si comporta come HttpResponse ma usa il codice di stato 403.
- HttpResponseNotAllowed
- Si comporta come HttpResponse ma usa il codice di stato 405. Accetta un solo argomento, richiesto: una lista di metodi ammessi (ad esempio, ['GET', 'POST']).
- HttpResponseGone
- Si comporta come HttpResponse ma usa il codice di stato 410.
- HttpResponseServerError
- Si comporta come HttpResponse ma usa il codice di stato 500.