Django-fr | Documentation | Les objets requête et réponse

Django-fr

Documentation Django

Les objets requête et réponse

Rapide survol

Django utilise les objets requête et réponse pour fournir l'état au système.

Quand une page est demandée, Django crée un objet HttpRequest qui contient des métadonnées relatives à la requête. Puis, Django charge la vue appropriée en lui passant l'HttpRequest en premier argument de la fonction de vue. Chaque vue est chargée de retourner un objet HttpResponse.

Ce document détaille les APIs des objets HttpRequest et HttpResponse.

Objets HttpRequest

Attributs

Tous les attributs en dehors de session doivent être considérés en lecture seule.

path

Une chaîne de caractères représentant le chemin complet de la page demandée, n'incluant pas le domaine.

Exemple: "/musique/groupes/the_beatles/"

method

Une chaîne de caractères représentant la méthode HTTP utilisée dans la requête. Elle est garantie en majuscules. Exemple:

if request.method == 'GET':
    faire_quelque_chose()
elif request.method == 'POST':
    faire_quelque_chose_d_autre()
encoding
Nouveau dans la version de développement de Django Une chaîne de caractères spécifiant l'encodage courant utilisé pour décoder les données soumises par le formulaire (ou None, signifiant que le paramètre DEFAULT_CHARSET est utilisé). Vous pouvez modifier cet attribut pour changer l'encodage utilisé lorsque vous accédez aux données de formulaire. Tout appel à un attribut subséquent (tel que la lecture de GET ou POST) utilisera la nouvelle valeur encoding. Utile si vous savez que les données de formulaire n'ont pas le même encodage que celui défini par DEFAULT_CHARSET.
GET
Un objet pseudo-dictionnaire contenant tous les paramètres HTTP GET donnés. Voir la documentation de QueryDict ci-dessous.
POST

Un objet pseudo-dictionnaire contenant tous les paramètres HTTP POST donnés. Voir la documentation de QueryDict ci-dessous.

Il est possible qu'une requête puisse parvenir en POST avec un dictionnaire POST vide -- si, imaginons, un formulaire est transmis via la méthode HTTP POST mais sans inclure de donnée de formulaire. En conséquence, vous ne devriez pas utiliser if request.POST pour vérifier l'utilisation de la méthode POST; utilisez, à la place, if request.method == "POST" (voir plus haut).

Note: POST n'inclue pas d'informations sur le transfert de fichier. Voir FILES.

REQUEST

Par commodité, un objet pseudo-dictionnaire recherchant d'abord dans POST puis dans GET. Inspiré par le $_REQUEST de PHP.

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

Il est hautement recommandé d'utiliser GET et POST au lieu de REQUEST, car les premiers sont plus explicites.

COOKIES
Un dictionnaire Python standard contenant tous les cookies. Les clés et les valeurs sont des chaînes de caractères.
FILES

Un objet pseudo-dictionnaire contenant tous les fichiers transférés. Chaque clé de FILES est la propriété name de <input type="file" name="" />. Chaque valeur de FILES est un dictionnaire Python standard contenant les trois clés suivantes:

  • filename -- Le nom du fichier transféré, en tant que chaîne de caractères Python.
  • content-type -- Le type de contenu du fichier transféré.
  • content -- Le contenu brut du fichier transféré.

Notez que FILES ne contiendra des données que si la méthode de transfert est POST et que le <form> qui a envoyé les données possède un enctype="multipart/form-data". Sans quoi, FILES sera un objet pseudo-dictionnaire vide.

META

Un dictionnaire Python standard contenant tous les entêtes HTTP disponible. Les entêtes disponibles dépendent du client et du serveur, mais voici quelques exemples:

  • CONTENT_LENGTH
  • CONTENT_TYPE
  • HTTP_ACCEPT_ENCODING
  • HTTP_ACCEPT_LANGUAGE
  • HTTP_HOST -- L'entête HTTP Host envoyé par le client.
  • HTTP_REFERER -- La page référant, si elle existe.
  • HTTP_USER_AGENT -- L'agent-utilisateur du client (chaîne de caractères).
  • QUERY_STRING -- La chaîne de recherche, une unique chaîne de caractères (non analysée).
  • REMOTE_ADDR -- L'adresse IP du client.
  • REMOTE_HOST -- Le nom d'hôte du client.
  • REQUEST_METHOD -- Une chaîne de caractères telle que "GET" ou "POST".
  • SERVER_NAME -- Le nom d'hôte du serveur.
  • SERVER_PORT -- Le numéro de port du serveur.
user

Un objet django.contrib.auth.models.User représentant l'utilisateur actuellement connecté. Si l'utilisateur n'est pas connecté, user sera une instance de django.contrib.auth.models.AnonymousUser. Vous pourrez faire la distinction via is_authenticated(), comme suit:

if request.user.is_authenticated():
    # Faire quelquechose avec l'utilisateur connecté.
else:
    # Faire quelquechose pour les utilisateurs anonymes.

user est disponible seulement si votre installation Django contient l' AuthenticationMiddleware activé. Pour en en savoir plus, voir l' Authentification au travers des requêtes web.

session

Un objet pseudo-dictionnaire en lecture et écriture représentant la session courante. Disponible uniquement si votre installation de Django à le support des sessions activé. Voir la documentation sur la session pour plus de détails.

raw_post_data
Les données HTTP POST brutes. Utile pour le traitement avancé. Utilisez POST à la place.

Méthodes

__getitem__(key)

Retourne la valeur GET/POST pour la clé donnée, vérifiant POST en premier, puis GET. Lève une erreur KeyError si la clé n'existe pas.

Ceci vous permet d'utiliser une syntaxe d'accès aux données de type dictionnaire sur une instance HttpRequest. Exemple : request["foo"] retournerait True si l'un des request.POST ou request.GET possède "foo" en clé.

has_key()
Retourne True ou False, vérifiant si request.GET ou request.POST possède la clé donnée.
get_host()

Nouveau dans la version de développement de Django

Retourne l'hôte d'origine de la requête en utilisant les informations des entêtes HTTP_X_FORWARDED_HOST et HTTP_HOST (dans cet ordre). S'ils ne fournissent aucune valeur, la méthode utilise une combinaison du SERVER_NAME et du SERVER_PORT comme détaillé dans le PEP 333.

Exemple: "127.0.0.1:8000"

get_full_path()

Retourne le path, plus l'ajout d'une chaîne de requête, si applicable.

Exemple: "/musique/groupes/les_beatles/?imprimer=true"

build_absolute_uri(adresse)

Nouveau dans la version de développement de Django

Retourne l'URI absolue de l'adresse. Si aucune adresse n'est fourni, l'adresse sera définie par request.get_full_path().

Si l'adresse est déjà une URI absolue, elle restera inchangée. Sinon, l'URI absolue est construite à partir des variables serveur définies dans la requête.

Exemple: "http://exemple.com/musique/groupes/les_beatles/?imprimer=true"

is_secure()
Retourne True si la requête est sécurisée; c'est-à-dire, si elle est effectuée avec HTTPS.

Objets QueryDict

Dans un objet HttpRequest, les attributs GET et POST sont des instances de django.http.QueryDict. QueryDict est une classe pseudo-dictionnaire modifiée pour gérer les valeurs multiples d'une même clé. Ceci est nécessaire du fait que certains éléments de formulaire HTML, notamment <select multiple="multiple">, passent plusieurs valeurs pour la même clé.

Les instances QueryDict sont immuables, à moins d'en créer une copy(). C'est-à-dire que vous ne pouvez pas changer les attributs de request.POST et request.GET directement.

QueryDict implémente la totalité des méthodes dictionnaire standards, puisqu'il s'agit d'une sous-classe de dictionnaire. Les exceptions sont présentées ci-dessous:

  • __getitem__(key) -- Retourne la valeur de la clé donnée. Si la clé possède plus d'une valeur, __getitem__() retourne la dernière valeur. Lève django.utils.datastructure.MultiValueDictKeyError si la clé n'existe pas. (C'est une sous-classe de la classe Python standard KeyError, vous pouvez donc vous contentez d'attraper une KeyError.)

  • __setitem__(key, value) -- Assigne [value] (une liste Python dont le seul élément est value) à la clé donnée. Notez que celle-ci, comme d'autres fonctions dictionnaires possédant des effets de bord, peut seulement être appelée sur un QueryDict mutable (pouvant être créé via copy()).

  • __contains__(key) -- Retourne True si la clé donnée est assignée. Ceci vous permet de faire, e.g., if "foo" in request.GET.

  • get(key, default) -- Utilise la même logique que __getitem__() ci-dessus, modulo le renvoi d'une valeur par défaut si la clé n'existe pas.

  • has_key(key)

  • setdefault(key, default) -- Identique à la méthode de dictionnaire standard setdefault(), sauf qu'elle utilise __setitem__ en interne.

  • update(other_dict) -- Prend en paramètre aussi bien un QueryDict qu'un dictionnaire standard. Identique à la méthode de dictionnaire standard update(), sauf qu'elle ajoute les éléments au dictionnaire courant au lieu de les remplacer. Par exemple:

    >>> q = QueryDict('a=1')
    >>> q = q.copy() # pour le rendre mutable
    >>> q.update({'a': '2'})
    >>> q.getlist('a')
    ['1', '2']
    >>> q['a'] # retourne la dernière valeur
    ['2']
    
  • items() -- Identique à la méthode de dictionnaire standard items(), sauf qu'elle utilise la même logique de dernière valeur que __getitem()__. Par exemple:

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

    >>> q = QueryDict('a=1&a=2&a=3')
    >>> q.values()
    ['3']
    

En outre, QueryDict possède les méthodes suivantes:

  • copy() -- Retourne une copie de l'objet, utilisant copy.deepcopy() de la bibliothèque standard Python. La copie sera mutable -- c'est-à-dire, que vous pouvez changer ses valeurs.

  • getlist(key) -- Retourne les données de la clé donnée, en tant que liste Python. Retourne une liste vide si la clé n'existe pas. Il est garantie qu'une liste soit retournée quoiqu'il arrive..

  • setlist(key, list_) -- Assigne la clé donnée à la list_ (contrairement à __setitem__()).

  • appendlist(key, item) -- Ajoute un élément à la liste interne associée à une clé.

  • setlistdefault(key, default_list) -- Identique à setdefault, sauf qu'elle prend une liste de valeurs au lieu d'une seule valeur.

  • `lists() -- Identique à items(), sauf qu'elle inclue toutes les valeurs, en tant que liste, pour chaque élément du dictionnaire. Par exemple:

    >>> q = QueryDict('a=1&a=2&a=3')
    >>> q.lists()
    [('a', ['1', '2', '3'])]
    
  • urlencode() -- Retourne une chaîne de caractères issue des données sous forme d'une chaîne de requête. Exemple: "a=2&b=3&b=5".

Exemples

Voici un exemple de formulaire HTML et comment Django traite les données reçues:

<form action="/foo/bar/" method="post">
<input type="text" name="votre_nom" />
<select multiple="multiple" name="groupes">
    <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 entre "John Smith" dans le champ votre_nom et sélectionne "The Beatles" et "The Zombies" dans le champ de sélection multiple, voici à quoi l'objet requête de Django ressemblera:

>>> request.GET
{}
>>> request.POST
{'votre_nom': ['John Smith'], 'groupes': ['beatles', 'zombies']}
>>> request.POST['votre_nom']
'John Smith'
>>> request.POST['groupes']
'zombies'
>>> request.POST.getlist('groupes')
['beatles', 'zombies']
>>> request.POST.get('votre_nom', 'Adrian')
'John Smith'
>>> request.POST.get('champ_inexistant', 'Perdu mon ami ?')
'Perdu mon ami ?'

Notes sur l'implementation

Les attributs GET, POST, COOKIES, FILES, META, REQUEST, raw_post_data et user sont tous chargés au minimun. C'est-à-dire que Django ne dépense aucune ressource pour calculer les valeurs de ces attributs tant que votre code ne les utilise pas.

Les objets HttpResponse

Contrairement aux objets HttpRequest, créés automatiquement par Django, les objets HttpResponse sont de votre ressort. Chaque vue que vous écrivez est responsable de l'instanciation, la définition et le retour d'un HttpResponse.

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

Utilisation

Passage de chaîne de caractères

L'utilisation typique est de passer le contenu d'une page, en tant que chaîne de caractères, au constructeur HttpResponse:

>>> response = HttpResponse("Le texte de la page Web.")
>>> response = HttpResponse("Texte uniquement, s'il vous plaît.", mimetype="text/plain")

Mais si vous voulez ajouter du contenu au fil de l'eau, vous pouvez utiliser response comme un objet pseudo-fichier:

>>> response = HttpResponse()
>>> response.write("<p>Le texte de la page Web.</p>")
>>> response.write("<p>Un autre paragraphe.</p>")

Vous pouvez ajouter et supprimer des entêtes en utilisant la syntaxe dictionnaire:

>>> response = HttpResponse()
>>> response['X-DJANGO'] = "C'est le meilleur."
>>> del response['X-PHP']
>>> response['X-DJANGO']
"C'est le meilleur."

Notez que del ne lève pas de KeyError si l'entête n'existe pas.

Passage d'itérateurs

Finalement, vous pouvez passer un itérateur à HttpResponse au lieu d'une chaîne de caractères en dur. Si vous utilisez cette technique, suivez ce schéma:

  • L'itérateur doit retourner des chaînes de caractères.
  • Si un HttpResponse a été initialisé avec un itérateur comme contenu, vous ne pouvez pas utiliser l'instance HttpResponse comme un objet pseudo-fichier. Le faire léverai une Exception.

Méthodes

__init__(content='', mimetype=None, status=200, content_type=DEFAULT_CONTENT_TYPE)

Instancie un objet HttpResponse avec le contenu de page donné (une chaîne de caractères) et le type MIME. Le DEFAULT_CONTENT_TYPE est 'text/html'.

content peut être un itérateur ou une chaîne de caractères. S'il s'agit d'un itérateur, il doit retourner des chaînes de caractères, et celles-ci seront concaténées une à une pour former le contenu de la réponse.

status est le code de statut HTTP de la réponse.

(Nouveau dans la version de développement de Django) content_type est un alias de mimetype. Historiquement, le paramètre était uniquement appelé mimetype, mais depuis qu'il s'agit de la valeur directement utilisée pour l'entête HTTP Content-Type, il peut aussi inclure le jeu d'encodage des caractères, ce qui fait de lui plus qu'une simple spécification MIME. Si mimetype est spécifié (différent de None), cette valeur est utilisée. Sinon, content_type est utilisé. Si aucun des deux n'est fourni, le paramètre DEFAULT_CONTENT_TYPE est utilisé.

__setitem__(header, value)
Assigne le nom d'entête donné avec la valeur donnée. Les deux, header et value, doivent être des chaînes de caractères.
__delitem__(header)
Supprime l'entête correspondant au nom donné. Echoue silencieusement si l'entête n'existe pas. Insensible à la casse.
__getitem__(header)
Retourne la valeur correspondante au nom d'entête donné. Insensible à la casse.
has_header(header)
Retourne True ou False basée sur une vérification insensible à la casse pour un entête correspondant au nom donné.
set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)

Assigne un cookie. Les paramètres sont les mêmes que l'objet cookie Morsel de la bibliothèque Python standard.

  • max_age doit être un nombre de secondes, ou None (par défaut) si le cookie ne dure que la session du navigateur client.
  • expires doit être une chaîne de caractères au format "Wdy, DD-Mon-YY HH:MM:SS GMT".
  • Utilisez domain si vous voulez assigner un cookie sur plusieurs domaines. Par exemple, domain=".lawrence.com" assignera un cookie accessible en lecture sur les domaines www.lawrence.com, blogs.lawrence.com et calendars.lawrence.com. Autrement, le cookie ne sera accessible en lecture que sur son domaine de définition.
delete_cookie(key, path='/', domain=None)

Supprime le cookie associé à la clé donnée. Echoue silencieusement si la clé n'existe pas.

Du fait du fonctionnement des cookies, path et domain doivent avoir les mêmes valeurs que celles utilisées avec set_cookie() -- autrement, le cookie ne sera pas détruit.

content
Retourne le contenu en tant que chaîne de caractères Python, l'encodant à partir d'un objet Unicode si nécessaire. Notez qu'il s'agit d'une propriété, et non d'une méthode, donc utilisez r.content au lieu de r.content().
write(content), flush() et tell()
Ces méthodes font d'une instance HttpResponse un objet pseudo-fichier.

Sous-classes d'HttpResponse

Django vient avec un nombre de sous-classes d'HttpResponse gérant plusieurs types de réponses HTTP. Tout comme HttpResponse, ces sous-classes résident dans django.http.

HttpResponseRedirect
Le constructeur prend un unique argument -- le chemin de redirection. Ce peut être une URL complète (e.g. 'http://www.yahoo.com/search/') ou une URL absolue sans domaine (e.g. '/search/'). Notez que cela retournera un code de statut HTTP 302.
HttpResponsePermanentRedirect
Identique à HttpResponseRedirect, mais retourne une redirection permanente (code de statut HTTP 301) au lieu d'une redirection simple (code de statut 302).
HttpResponseNotModified
Le constructeur ne prend pas d'arguments. Utilisez celle-ci pour notifier qu'une page n'a pas été modifiée depuis la dernière requête de l'utilisateur.
HttpResponseBadRequest
Nouveau dans la version de développement de Django. Agit exactement comme un HttpResponse mais avec un code de statut 400.
HttpResponseNotFound
Agit exactement comme un HttpResponse mais avec un code de statut 404.
HttpResponseForbidden
Agit exactement comme un HttpResponse mais avec un code de statut 403.
HttpResponseNotAllowed
Identique à HttpResponse, mais avec un code de statut 405. Prends un unique argument obligatoire: une liste de méthodes permises (e.g. ['GET', 'POST']).
HttpResponseGone
Agit exactement comme un HttpResponse mais avec un code de statut 410.
HttpResponseServerError
Agit exactement comme un HttpResponse mais avec un code de statut 500.

Retourner des erreurs

Retourner des erreurs en Django est aisé. Nous avons déjà mentionné les sous-classes HttpResponseNotFound, HttpResponseForbidden, HttpResponseServerError, etc.; retournez simplement une instance de l'une de ces sous-classes au lieu d'un HttpResponse normal dans le but de signifier une erreur. Par exemple:

def ma_vue(request):
    # ...
    if foo:
        return HttpResponseNotFound('<h1>Page non trouvée</h1>')
    else:
        return HttpResponse('<h1>Page trouvée</h1>')

Les erreurs 404 étant les erreurs HTTP les plus courante, il y a une manière plus simple de gérer ce genre d'erreurs.

L'exception Http404

Lorsque vous retournez une erreur telle que HttpResponseNotFound, vous êtes responsable de la définition du code HTML résultant pour la page d'erreur:

return HttpResponseNotFound('<h1>Page non trouvée</h1>')

Par commodité, et parce que c'est une bonne idée de disposer d'une page d'erreur 404 consistente pour votre site, Django fourni une exception Http404. Si vous levez un Http404 n'importe où dans votre fonction de vue, Django l'attrapera et retournera une page d'erreur standard pour votre application, contenant un code d'erreur HTTP 404.

Exemple d'utilisation:

from django.http import Http404

def detail(request, vote_id):
    try:
        p = Vote.objects.get(pk=vote_id)
    except Vote.DoesNotExist:
        raise Http404
    return render_to_response('votes/detail.html', {'vote': p})

Pour complètement utiliser une exception Http404, vous devez créer un gabarit qui sera affiché lorsqu'une erreur 404 sera levée. Ce gabarit doit être appelé 404.html et doit résider au premier niveau de votre arborescence de gabarits.

Personnaliser les erreurs de vues

La vue 404 (page non trouvée)

Lorsque que vous levez une exception Http404, Django charge une vue spéciale dévolue à la gestion des erreurs 404. Par défaut, il s'agit de la vue django.views.defaults.page_not_found, qui charge et rend le gabarit 404.html.

Ceci implique que vous définissiez un gabarit 404.html à la racine de votre répertoire de gabarits. Ce gabarit sera utilisé pour toutes les erreurs 404.

Cette vue page_not_found devrait suffire à 99% des applications Web, mais si vous désirez surcharger la vue 404, vous pouvez spécifier un handler404 dans votre URLconf, tel que:

handler404 = 'monsite.views.ma_vue_404'

En coulisse, Django identifie la vue 404 en regardant du côté du handler404. Par défaut, les URLconfs contiennent la ligne suivante:

from django.conf.urls.defaults import *

Ceci se charge de définir le handler404 du module courant. Comme vous pouvez le voir dans django/conf/urls/defaults.py, le handler404 est défini à 'django.views.defaults.page_not_found' par défaut.

Trois choses à noter à propos des vues 404:

  • La vue 404 est aussi appelée si Django ne trouve aucun résultat après avoir passé en revue chaque expression régulière de l'URLconf.
  • Si vous ne définissez pas votre propre vue 404 -- utilisant simplement celle par défaut, ce qui est recommandé -- vous avez quand même une obligation: Créer un gabarit 404.html à la racine de votre répertoire de gabarits. La vue 404 par défaut utilisera ce gabarit pour toutes les erreurs 404. La vue 404 par défaut passera une variable au gabarit : request_path, qui est l'URL résultante du 404.
  • Il est passé un RequestContext à la vue 404, ce qui lui donnera accès aux variables fournies par votre propriété TEMPLATE_CONTEXT_PROCESSORS (e.g., MEDIA_URL).
  • Si DEBUG contient la valeur True (dans vos paramètres de configuration de module) alors votre vue ne sera jamais utilisée, et le contexte de débogage sera affiché par défaut.

La vue 500 (erreur serveur)

De manière similaire, Django exécute un comportement spécial dans le cas d'une erreur à l'exécution au niveau de votre vue. Si la vue s'achève par une exception, Django appellera, par défaut, la vue django.views.defaults.server_error, qui charge et rend le gabarit 500.html.

Ceci implique que vous définissiez un gabarit 500.html à la racine de votre répertoire de gabarits. Ce gabarit sera utilisé pour toutes les erreurs internes au serveur. La vue 500 par défaut ne passe aucune variable à ce gabarit et est rendue avec un Context vide pour minimiser le risque d'erreurs additionnelles.

Cette vue server_error devrait suffire à 99% des applications Web, mais si vous voulez surcharger cette vue, vous pouvez spécifier un handler500 dans votre URLconf, tel que:

handler500 = 'monsite.views.ma_vue_d_erreur'

En coulisse, Django identifie la vue d'erreur en recherchant le handler500. Par défaut, les URLconfs contiennent la ligne suivante:

from django.conf.urls.defaults import *

Ceci ce charge de configurer le handler500 pour le module courant. Comme vous pouvez le voir dans django/conf/urls/defaults.py, handler500 est assigné à 'django.views.defaults.server_error' par défaut.