<< précédent

Annexe H: Les objets Request et Response

Django utilise les objets Request et response pour transmettre un état au sein du système.

Lorsqu’une page est demandée, Django crée un objet HttpRequest qui contient les métadonnées de la requête. Ensuite Django charge la vue appropriée, passant le HttpRequest en premier arguement à la fonction vue. Chaque vue est responsable du renvoie d’un objet HttpResponse.

Nous avons utilisé ces objrts très souvent tout au long du livre; cette annexe détaille les API complètes pour les objets HttpRequest et HttpResponse.

HttpRequest

HttpRequest représente une requête unique faite par un agent utilisateur quelconque.

La plupart des informations importantes au sujet de la requête est disponible sous forme d’attributs de l’instance HttpRequest (voir le Tableau H-1). Tous les attributs à l’exception de session doivent être considérés comme étant en lecture seule.

Tableau H-1. Attributs des objets HttpRequest

Attribut Description
path Une chaîne représentant le chemin complet vers la page demandée, sans inclure le domaine - par exemple, "/music/bands/the_beatles/".
method

Une chaîne représentant la méthode HTTP utilisée dans la requête. Avec la garantie d’être en lettres capitales. Par exemple:

if request.method == 'GET':
    do_something()
elif request.method == 'POST':
    do_something_else()
GET Objet similaire à un dictionnaire contenant touts les paramètres HTTP GET donnés. Consultez la documentation de QueryDict.
POST

Objet similaire à un dictionnaire contenant touts les paramètres HTTP GET donnés. Consultez la documentation de QueryDict.

Il est possible qu’une requête arrive via POST avec un dictionnaire POST vide - si, admettons, un formulaire est requis via la méthode HTTP POST sans inclure les données du formulaire. Par conséquent, vous ne devrez pas utiliser if request.POST pour vérifier l’utilisation de la méthode POST; au lieu de cela, utilisez if request.method == "POST" (consultez l’entrée méthode de ce tableau).

Note: POST n’inclu pas les informations d’envoi de fichier. Consultez FILES.

REQUEST

Par commodité, un objet similaire à un dictionnaire qui recherche d’abord POST, puis GET . Inspiré des $_REQUEST en PHP.

Par exemple, si GET = {"name": "john"} et POST = {"age": '34'}, REQUEST["name"] sera "john", et REQUEST["age"] sera "34".

Il est fortement conseillé d’utiliser GET et POST à la place de REQUEST, car les premières sont plus explicites.

COOKIES Un dictionnaire Python standard qui contient tous les cookies. Les clefs et valeurs sont des chaînes. Voyer les chapitre 12 pour plus d’informations sur l’utilisation des cookies.
FILES

Un objet similaire à un dictionnaire contenant tous les fichiers envoyés. Chaque clef dans FILES à le nom name provenant de <input type="file" name="" />. Chaque valeur dans FILES est un dictionnaire Python standard contenant les trois clefs suivantes:

-filename: The name of the uploaded file, as a Python string -content-type: Le type de contenu du fichier chargé. -content: Le contenu brut du fichier chargé.

Notez que FILES contiendra des données uniquement si la méthode de requête est POST et que le <form> qui a posté vers la requête contient enctype="multipart/form-data". Sinon, FILES sera un objet similaire à un dictionnaire vide.

META

Un dictionnaire Python standard contenant toutes les en-têtes HTTP disponibles. Les en-têtes disponibles dépendent du client et du serveur, mais voici quelques exemples:

-CONTENT_LENGTH -CONTENT_TYPE -QUERY_STRING: La chaîne de requête brute et non traitée -REMOTE_ADDR: L’adresse IP du client -REMOTE_HOST: Le nom d’hôte du client -SERVER_NAME: Le nom d’hôte du serveur -SERVER_PORT: Le port du serveur

Tout en-têtes HTTP est disponible dans META sous forme de clef préfixée par HTTP_, par exemple:

-HTTP_ACCEPT_ENCODING -HTTP_ACCEPT_LANGUAGE -HTTP_HOST: L’en-tête HTTP Host``envoyée par le client -``HTTP_REFERER: La page référente, si disponible -HTTP_USER_AGENT: La chaîne agent utilisateur du client -HTTP_X_BENDER: La valeur de l’en-tête X-Bender, si fixée

user

Un objet django.contrib.auth.models.User représentant l’utilisateur actuellement connecté. Si l’utilisateur n’est pas actuellement connecté, user sera fixée à une instance de django.contrib.auth.models.AnonymousUser. Vous pouvez les distinguer grâce à is_authenticated(), comme ceci:

if request.user.is_authenticated():
    # Do something for logged-in users.
else:
    # Do something for anonymous users.

user est disponible uniquement si votre installation Django possède le AuthenticationMiddleware activaté.

Pour des détails complets sur l’authentification et les utilisateurs, lisez le chapitre 12.

session Un objet similaire à un dictionnaire, accessible en écriture et en lecture, qui représente la session courante. Ceci est diponible uniquement si votre installation Django à le support de session activé. Lisez le chapitre 12.
raw_post_data Les données brutes HTTP POST. Ceci est utile pour les traitements avancés.

Les objets Request ont eux aussi des méthodes utilse, comme le montre le tableau H-2.

Table H-2. HttpRequest Methods

Method Description
__getitem__(key)

Renvoie la valeur GET/POST pour la clef donnée, en vérifiant d’abord POST, puis GET. Lève une KeyError si la clef n’existe pas.

Ceci vous permet d’utiliser la syntaxe d’accès au dictionnaire sur une instance HttpRequest.

Par exemple, request["foo"] est identique à la vérification de request.POST["foo"] puis ensuite de request.GET["foo"].

has_key() Renvoie True ou False, selon que request.GET ou request.POST contient la clef donnée.
get_full_path() Renvoie le path, plus une chaîne de requête ajoutée, si applicable. Par exemple, "/music/bands/the_beatles/?print=true" is_secure() renvoie True si la requête est sécure; c’est à dire, si elle à été faite avec HTTPS.

QueryDict Objects

Pour un objet HttpRequest, les attributs GET et POST sont des instances de django.http.QueryDict. QueryDict est une classe assimilable à un dictionnaire, et personnalisée pour gérer les valeurs multiples d’une même clef. Ceci est nécessaire parceque certains éléments de formulaire HTML, notablement <select multiple="multiple">, transmettent des valeurs multiples pour une même clef.

Les instances QueryDict sont immuables, à moins d’avoir créé une copy(). cela signifie que vous ne pouvez pas directement modifier les attributs de request.POST et request.GET.

QueryDict implemente toutes les méthodes standards des dictionnaires, puisque c’est une sous-classe de dictionnaire. Les exceptions sont abordées au Tableau H-3.

Table H-3. How QueryDicts Differ from Standard Dictionaries.

Method Differences from Standard dict Implementation
__getitem__ Fonctionne comme un dictionnaire. Cependant, si la clef à plus d’une valeur, __getitem__() renvoie la dernière valeur.
__setitem__ Fixe la clef donnée selon [value] (une liste Pytohn dont l’unique élément est value). Notez que, tout comme les autres fonctions de dictionnaire ayant des effets de bord, ceci peut être appellé uniquement sur un QueryDict mutable (une qui a été crée via copy()).
get() Si la clef a plsu d’une valeur, get() retourne la dernière valeur, tout comme __getitem__.
update()

Accepte indifférement un QueryDict ou un dictionnaire standard. À la différence de la méthode standard de dictionnaire update, cette méthode ajoute des éléments au dictionnaire courant au lieu de les remplacer:

>>> q = QueryDict('a=1')
>>> q = q.copy() # to make it mutable
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # returns the last
['2']
items()

Tout comme la méthode standard de dictionnaire items(), sauf qu’elle utilise la même logique de dernière valeur que __getitem()__:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.items()
[('a', '3')]
values() Tout comme la méthode standard de dictionnaire values(), sauf qu’elle utilise la même logique de dernière valeur que __getitem()__:

En complément, QueryDict propose les méthodes figurants dans le Tableau H-4.

H-4. Extra (Nondictionary) QueryDict Methods

Method Description
copy() Retourne une copie de l’objet, utilisant copy.deepcopy() de la bibliothèque standard Python. La compie sera mutable - c’est à dire vous pouvez modifier ses valeurs.
getlist(key) Retourne les données et la clef requise, sous forme de liste Python. Renvoie une liste vide si la clef n’existe pas. Elle retourne de toute les façons une liste.
setlist(key, list_) Fixe la clef indiquée à list_ (à la différence de __setitem__()).
appendlist(key, item) Ajoute un élément à la liste interne associée à la key.
setlistdefault(key, l) Tout comme setdefault, à l’exception qu’elle prends une liste de valeur à la place d’une valeur unique.
lists()

Comme items(), à l’exception qu’elle inclu toutes les valeurs, sous forme de liste, pour chaque memebre du dictionnaire. Par exemple:

>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[('a', ['1', '2', '3'])]
urlencode() Renvoie une chaîne des données au format query-string (par exemple, "a=2&b=3&b=5").

Un exemple complet

Par exemple, considérons ce formulaire HTML:

<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>

Si l’utilisateur saisi "John Smith" dans le champ your_name et sélectionne à la fois «The Beatles» et «The Zombies» dans la boîte de sélection multiple, voici ce que l’objet requête contiendra:

>>> 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 d’implémentation:

Les attributs GET, POST, COOKIES, FILES, META, REQUEST, raw_post_data, et user sont tous chargés à minima. Cela signifie que Django n’utilise pas de ressources en calculant les valeurs de ces attributs avant que le code ne les demande.

HttpResponse

Par contraste avec les objets HttpRequest, qui sont créés automatiquement par Django, les objets HttpResponse sont de votre ressort. Chaque vue que vous écrivez est responsable de l’instanciation, du peuplement, et du renvoi de HttpResponse.

La classe HttpResponse réside dans django.http.HttpResponse.

Construction des HttpResponses

Typiquement, vous construirez une HttpResponse pour transmettre le contenu de la page, sous forme de chaîne, au contructeur de HttpResponse:

>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.",
mimetype="text/plain")

Mais si voulez ajouter du contenu de façon incrémentale, vous pouvez utiliser response comme un objet similaire à un objet:

>>> response = HttpResponse()
>>> response.write("<p>Here's the text of the Web page.</p>")
>>> response.write("<p>Here's another paragraph.</p>")

Vous pouvez passer à HttpResponse un itérateur au lieu de passer sa chaîne codée en dure. Si vous utilisez cette technique, suivez ces règles:

  • L’itérateur doit retourner des chaînes.
  • Si une HttpResponse a été initialisée avec un itérateur pour contenu, vous ne pouvez pas utiliser l’instance HttpResponse comme un objet de type fichier. Faire ainsi lévera une Exception.

Finallement, notez que HttpResponse implémente une méthode write(), qui est disponible pour être utilisée partout où Python attends un objet assimilable à un fichier. Consultez le chapitre 11 pour des exemples d’utilisation de cette technique.

Paramètre d’en-têtes

Vous pouvez ajouter et supprimer les en-têtes en utilisant la syntaxe des dictionnaires:

>>> response = HttpResponse()
>>> response['X-DJANGO'] = "It's the best."
>>> del response['X-PHP']
>>> response['X-DJANGO']
"It's the best."

Vous pouvez aussi utiliser has_header(header) pour vérifier l’existence d’une en-tête.

Évitez de paramétrer l’en-tête Cookie à la main; au lieu de cela, lisez le chapitre 12 pour connaître le fonctionnement des cookies sous Django.

Sous classes de HttpResponse

Django inclu de nombreuses sous classes de HttpResponse qui gèrent différents types de reponses HTTP (voir le Tableau H-5). Comme HttpResponse, ces sous classes résident dans django.http.

Table H-5. HttpResponse Subclasses

Class Description
HttpResponseRedirect Le constructeur prends un unique argument: le chemin de redirection. Ce peut être un URL pleinement qualifié (par exemple, 'http://search.yahoo.com/') ou un URL absolu sans le domaine (par exemple, '/search/'). Notez que ceci retourne un code HTTP de status 302.
HttpResponsePermanentRedirect Comme HttpResponseRedirect, mais renvoie une redirection permanente (status HTTP code 301) à la place d’une redirection «trouvée» (status code 302).
HttpResponseNotModified Le constructeur n’accepte pas d’arguments. Utilisez ceci pour indiquer qu’une page n’a pas été modifiée depuis la dernière requête de l’utilisateur.
HttpResponseBadRequest Agit comme HttpResponse mais utilise un code de status 400.
HttpResponseNotFound Agit comme HttpResponse mais utilise un code de status 404.
HttpResponseForbidden Agit comme HttpResponse mais utilise un code de status 403.
HttpResponseNotAllowed Comme HttpResponse, mais utilise un code de status 405. Nécessite un seul argument, requis: une liste des méthodes autorisées (par exemple, ['GET', 'POST']).
HttpResponseGone Agit comme HttpResponse mais utilise un code de status 410.
HttpResponseServerError Agit comme HttpResponse mais utilise un code de status 500.

Vous pouvez, bine sur, définir votre propre sous classe HttpResponse pour supporter différents types de réponses qui ne soient pas supportées nativement.

Renvoyer les erreurs

Retourner les codes d’erreur HTTP sous Django est facile. Nous avons déjà mentionné HttpResponseNotFound, HttpResponseForbidden, HttpResponseServerError, et autres sous classes. Retournez une instance de l’une de ces sous classes à la place d’une HttpResponse normale de façon à préciser une erreur, par exemple:

def my_view(request):
    # ...
    if foo:
        return HttpResponseNotFound('<h1>Page not
        found</h1>')
    else:
        return HttpResponse('<h1>Page was found</h1>')

Puisque l’erreur 404 est de loin l’erreur HTTP la plsu commune, il existe une façon simple de les gérer.

Lorsque vous retournez une erreur telle que HttpResponseNotFound, vous êtes responsable de définir le HTML de la page d’erreur résultante:

return HttpResponseNotFound('<h1>Page not found</h1>')

Par commodité, et puisque c’est une bonne idée d’avoir une page d’erreur 404 consistante au sein de votre site, Django founrit une exception Http404. Si vous levez Http404 à n’importe quel endroit d’une fonction vue, Django l’attrapera et retournera la page d’erreur standard pour votre application, avec un code d’erreur HTTP 404.

Voici un exemple:

from django.http import Http404

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404
    return render_to_response('polls/detail.html', {'poll': p})

De façon à utiliser l’exception Http404 à son plein, vous devez créer un gabarit qui est affiché lorsqu’une erreur 404 est levée. Ce gabarit doit être nommé 404.html, et doit être situé à la racine de votre arborescence de gabarit.

Personnaliser la vue 404 (Not Found)

Lorsque vous levez une exception Http404, Django charge une vue spéciale dédiéé à la prise en charge des erreurs 404. Par défault, c’est la vue django.views.defaults.page_not_found, qui charge et retourne le gabarit 404.html.

Ceci signifie que vous devez définir un gabarit 404.html dans la racine de votre répertoire de gabarit. Ce gabarit sera utilisé pour toutes les erreurs 404.

Cette vue page_not_found doit suffire pour 99% des applications web, mais si vous voulez écraser la vue 404, vous pouvez spécifier handler404 dans votre URLconf, comme ceci:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    ...
)

handler404 = 'mysite.views.my_custom_404_view'

En coulisse, Django détermine la vue 404 en recherchant le handler404. Par défaut, URLConfs contient la ligne suivante:

from django.conf.urls.defaults import *

Ceci prends soin de paramétrer handler404 dans le module courant. Comme vous pouvez le voir dans django/conf/urls/defaults.py, handler404 est fixé à 'django.views.defaults.page_not_found' par défaut.

Il y a trois choses à noter au sujet des vues 404:

  • La vue 404 est aussi appellée si Django ne trouve pas de correspondance après avoir vérifié chaque expression régulière présente dans l’URLConf.
  • Si vous ne définissez pas votre propre vue 404 - et utilisez simplement celle par défaut, ce qui est recommandé - vous aurez toujours une obligation: pour créer un gabarit 404.html dans la racine de votre répertoire de gabarit. La vue 404 par défaut utilisera ce gabarit pour toutes les erreurs 404.
  • Si DEBUG est fixé à True (dans votre module «settings»), alors votre vue 404 ne sera jamais utilisée, et le rapport d’erreur sera affiché à la place.

Personnaliser la vue 500 (Server Error)

De la même façon, Django à un comportement spécifique dans le cas d’une erreur d’exécution au niveau du code de la vue. Si une vue génère une exception, Django appellera, par défaut, la vue django.views.defaults.server_error, qui chargera et retournera le gabarit 500.html.

Cela signifie que vous devez définir un gabarit 500.html à la racine de votre répertoire de gabarit. Ce gabarit sera utilisé pour toutes les erreurs relatives au serveur.

Cette vue server_error doit suffire pour 99% des applications web, mais si vous voulez écraser cette vue, vous pouvez spécifier handler500 dans votre URLconf, comme ceci:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    ...
)

handler500 = 'mysite.views.my_custom_error_view'

<< précédent

Dernière modification: 2008-08-04 13:39:39.695579