123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- <!doctype html>
- <html lang=fr>
- <head>
- <!-- Always define the charset before the title -->
- <meta charset=utf-8>
- <title>Rédaction de votre première appli Django, partie 3 : Création des vues de l'interface publique — Biologeek — David Larlet</title>
- <!-- Define a viewport to mobile devices to use - telling the browser to assume that the page is as wide as the device (width=device-width) and setting the initial page zoom level to be 1 (initial-scale=1.0) -->
- <meta name="viewport" content="width=device-width, initial-scale=1"/>
- <!-- Fake favicon, to avoid extra request to the server -->
- <link rel="icon" href="data:;base64,iVBORw0KGgo=">
- <link type="application/atom+xml" rel="alternate" title="Feed" href="/david/log/" />
- <link rel="manifest" href="/manifest.json">
-
- <link rel="stylesheet" href="/static/david/css/larlet-david-_J6Rv.css" data-instant-track />
-
- <noscript>
- <style type="text/css">
- /* Otherwise fonts are loaded by JS for faster initial rendering. See scripts at the bottom. */
- body {
- font-family: 'EquityTextB', serif;
- }
- h1, h2, h3, h4, h5, h6, time, nav a, nav a:link, nav a:visited {
- font-family: 'EquityCapsB', sans-serif;
- font-variant: normal;
- }
- </style>
- </noscript>
-
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique">
-
- </head>
- <body>
- <div>
-
- <header>
- <nav>
- <p>
- <small>
- Je suis <a href="/david/" title="Profil public">David Larlet</a>, <a href="/david/pro/" title="Activité professionnelle">artisan</a> du web qui vous <a href="/david/pro/accompagnement/" title="Activité d’accompagnement">accompagne</a><span class="more-infos"> dans l’acquisition de savoirs pour concevoir des <a href="/david/pro/produits-essentiels/" title="Qu’est-ce qu’un produit essentiel ?">produits essentiels</a></span>. <span class="more-more-infos">Discutons ensemble d’une <a href="/david/pro/devis/" title="En savoir plus">non-demande de devis</a>.</span> Je partage ici mes <a href="/david/blog/" title="Expériences bienveillantes">réflexions</a> et <a href="/david/correspondances/2017/" title="Lettres hebdomadaires">correspondances</a>.
- </small>
- </p>
- </nav>
- </header>
-
-
- <section>
- <h1 property="schema:name">Rédaction de votre première appli Django, partie 3 : Création des vues de l'interface publique</h1>
- <article typeof="schema:BlogPosting">
- <div property="schema:articleBody">
- <img src="/static/david/biologeek/images/logos/django.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
- <p>Ce tutoriel commence là où s'est achevé le <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-2-exploration-de-l-interface-d-admin-auto-generee/">Tutoriel 2</a>. Nous continuons
- l'application Web de sondage et allons nous focaliser sur la création
- d'interfaces publiques -- les « vues ».</p>
-
- <div class="section">
- <h1><a id="philosophie" name="philosophie">Philosophie</a></h1>
- <p>Une vue est un « type » de page Web dans votre application Django qui en général
- sert une fonctionnalité spécifique et possède un template spécifique. Par
- exemple, dans une application de weblog, vous pourriez avoir les vues suivantes:</p>
- <blockquote>
- <ul class="simple">
- <li>Page d'accueil du blog -- afficher quelques unes des dernières entrées.</li>
- <li>Page de « détail » d'un billet -- page au lien permanent pour un certain
- billet.</li>
- <li>Page d'archivage par années -- affiche tous les mois ayant des entrées
- dans une année donnée.</li>
- <li>Page d'archivage par mois -- affiche tous les jours ayant des entrées dans
- un mois donné.</li>
- <li>Page d'archivage par jour -- affiche toutes les entrées pour un jour
- donné.</li>
-
- <li>Action de commentaire -- gère l'envoi de commentaires pour un billet
- donné.</li>
- </ul>
- </blockquote>
- <p>Dans notre application de sondage, nous aurons les quatre vues suivantes:</p>
- <blockquote>
- <ul class="simple">
- <li>Page « d'archive » des sondages -- affiche quelques uns des derniers
- sondages.</li>
- <li>Page « de détail » de sondage -- affiche la question d'un sondage, sans
- les résultats mais avec un formulaire pour voter.</li>
- <li>Page « de résultat » de sondage -- affiche les résultats pour un sondage
- particulier.</li>
- <li>Action de vote -- gère le vote d'un choix particulier pour un sondage
- particulier.</li>
- </ul>
-
- </blockquote>
- <p>Dans Django, chaque vue est représentée par une simple fonction Python.</p>
- </div>
-
- <div class="section">
- <h1><a id="conception-de-vos-urls" name="conception-de-vos-urls">Conception de vos URLs</a></h1>
- <p>La première étape dans la rédaction de vues est de concevoir la structure de vos
- URLs. Vous faites cela en créant un module Python, appelé URLconf. Les URLconfs
- décrivent comment Django associe une URL donnée avec un code Python donné.</p>
- <p>Lorsqu'un utilisateur effectue une requête pour une page gérée par Django, le
- système examine l'option <tt class="docutils literal"><span class="pre">ROOT_URLCONF</span></tt>, qui contient une chaîne dans la
- syntaxe à points de Python. Django charge ce module et recherche une variable de
- module appelé <tt class="docutils literal"><span class="pre">urlpatterns</span></tt>, que est une séquence de tuples dans le format
- suivant:</p>
- <pre class="literal-block">
- (expression rationnelle, fonction Python de rappel [, dictionnaire facultatif])
-
- </pre>
- <p>Django démarre la première expression rationnelle et parcourt la liste, en
- comparant l'URL de la requête avec chaque expression rationnelle jusqu'à ce
- qu'il en trouve une qui corresponde.</p>
- <p>Quand il trouve une correspondance, Django appelle la fonction Python de rappel,
- avec un objet <tt class="docutils literal"><span class="pre">HTTPRequest</span></tt> en premier argument, toutes les valeurs
- « capturées » dans l'expression rationnelle sous forme d'arguments mot-clés, et,
- facultativement, un argument mot-clé arbitraire contenant un dictionnaire (le
- troisième élément facultatif du tuple).</p>
- <p>Pour plus d'infos sur les objets <tt class="docutils literal"><span class="pre">HTTPRequest</span></tt>, lisez la <a class="reference" href="http://www.djangoproject.com/documentation/request_response/">documentation sur
- les requêtes et réponses</a>.
- Pour plus de détails sur les URLconfs, lisez la <a class="reference" href="http://www.djangoproject.com/documentation/url_dispatch/">documentation URLconf</a>.</p>
- <p>Quand vous avez lancé <tt class="docutils literal"><span class="pre">python</span> <span class="pre">manage.py</span> <span class="pre">startproject</span> <span class="pre">monsite</span></tt> au début du
- Tutoriel 1, ça a créé un URLconf par défaut dans <tt class="docutils literal"><span class="pre">monsite/urls.py</span></tt>. Ça a aussi
- défini automatiquement votre option <tt class="docutils literal"><span class="pre">ROOT_URLCONF</span></tt> pour pointer vers ce
- fichier:</p>
-
- <pre class="literal-block">
- ROOT_URLCONF = 'monsite.urls'
- </pre>
- <p>Passons à un exemple. Éditez <tt class="docutils literal"><span class="pre">monsite/urls.py</span></tt> pour qu'il ressemble à ceci:</p>
- <pre class="literal-block">
- from django.conf.urls.defaults import *
-
- urlpatterns = patterns('',
- (r'^polls/$', 'monsite.polls.views.index'),
- (r'^polls/(?P<poll_id>\d+)/$', 'monsite.polls.views.detail'),
- (r'^polls/(?P<poll_id>\d+)/results/$', 'monsite.polls.views.results'),
- (r'^polls/(?P<poll_id>\d+)/vote/$', 'monsite.polls.views.vote'),
- )
- </pre>
-
- <p>Cela mérite quelques explications. Lorsque quelqu'un effectue une requête sur
- une page de votre site Web -- disons, « /polls/23/ », Django va charger ce
- module Python, parce qu'il est pointé par l'option <tt class="docutils literal"><span class="pre">ROOT_URLCONF</span></tt>. Ça trouve
- la variable nommée <tt class="docutils literal"><span class="pre">urlpatterns</span></tt> et parcourt les expressions rationnelles dans
- l'ordre. Quand il trouve une expression rationnelle qui correspond --
- <tt class="docutils literal"><span class="pre">r'^polls/(?P<poll_id>\d+)/$'</span></tt> -- il charge le module ou paquetage Python
- associé : <tt class="docutils literal"><span class="pre">monsite.polls.views.detail</span></tt>. Ce qui correspond à la fonction
- <tt class="docutils literal"><span class="pre">detail()</span></tt> dans <tt class="docutils literal"><span class="pre">mysite/polls/views.py</span></tt>.</p>
-
- <p>Enfin, il appelle cette fonction <tt class="docutils literal"><span class="pre">detail()</span></tt> comme ceci:</p>
- <blockquote>
- detail(request=<HttpRequest object>, poll_id='23')</blockquote>
- <p>La partie <tt class="docutils literal"><span class="pre">poll_id='23'</span></tt> vient de <tt class="docutils literal"><span class="pre">(?P<poll_id>\d+)</span></tt>. Mettre les parenthèses
- autour d'un masque (pattern) « capture » le texte correspondant à ce masque et
- l'envoie en argument à la fonction de vue. Le <tt class="docutils literal"><span class="pre">?P<poll_id></span></tt> définit le nom qui
- sera utilisé pour identifier le masque correspondant et <tt class="docutils literal"><span class="pre">\d+</span></tt> est une
- expression rationnelle pour trouver une séquence de chiffres (c'est-à-dire, un
- nombre).</p>
-
- <p>Parce que les masques d'URL sont des expressions rationnelles, il n'y a vraiment
- aucune limite sur ce que vous pouvez faire avec eux. Et il n'est pas nécessaire
- d'ajouter de fioritures à l'URL tel que <tt class="docutils literal"><span class="pre">.php</span></tt> -- sauf si vous avez un sens de
- l'humour tordu, dans lequel cas vous pouvez faire quelque chose comme ça:</p>
- <pre class="literal-block">
- (r'^polls/latest\.php$', 'monsite.polls.views.index'),
- </pre>
- <p>Mais, ne faites pas ça. C'est stupide.</p>
- <p>Notez que ces expressions rationnelles ne recherchent pas dans les paramètres
- GET et POST, ni dans le nom de domaine. Par exemple, dans une requête vers
- <tt class="docutils literal"><span class="pre">http://www.exemple.com/monappli/</span></tt>, l'URLconf va rechercher dans
- <tt class="docutils literal"><span class="pre">/monappli/</span></tt>. Dans une requête vers
- <tt class="docutils literal"><span class="pre">http://www.exemple.com/monappli/?page=3</span></tt>, l'URLconf va rechercher dans
-
- <tt class="docutils literal"><span class="pre">/myapp/</span></tt>.</p>
- <p>Si vous avez besoin d'aide sur les expressions rationnelles, lisez <a class="reference" href="http://en.wikipedia.org/wiki/Regular_expression">l'article de
- Wikipedia</a> et la <a class="reference" href="http://www.python.org/doc/current/lib/module-re.html">documentation Python</a>. De plus, le livre O'Reilly
- « Mastering Regular Expressions » de Jeffrey Friedl est fantastique.</p>
- <p>Pour finir, une note sur la performance: ces expressions rationnelles sont
- compilées la première fois que le modul URLconf est chargé. Ça les rend très
- rapides.</p>
- </div>
-
- <div class="section">
- <h1><a id="crire-votre-premi-re-vue" name="crire-votre-premi-re-vue">Écrire votre première vue</a></h1>
- <p>Bien, nous n'avons toujours pas créé de vue -- nous avons juste touché à
- URLconf. Mais assurons-nous que Django suit l'URLconf comme il faut.</p>
-
- <p>Lancez le serveur Web de développement de Django:</p>
- <pre class="literal-block">
- python manage.py runserver
- </pre>
- <p>Maintenant, allez sur « <a class="reference" href="http://localhost:8000/polls/">http://localhost:8000/polls/</a> » avec votre navigateur
- Web. Vous devriez obtenir une page d'erreur agréablement colorée avec
- le message suivant:</p>
- <pre class="literal-block">
- ViewDoesNotExist at /polls/
-
- Tried index in module mysite.polls.views. Error was: 'module'
- object has no attribute 'index'
- </pre>
- <p>Cette erreur survient parce que vous n'avez pas écrit la fonction <tt class="docutils literal"><span class="pre">index()</span></tt>
- dans le module <tt class="docutils literal"><span class="pre">monsite/polls/views.py</span></tt>.</p>
-
- <p>Essayez « /polls/23/ », « /polls/23/results/ » et « /polls/23/vote/ ». Les
- messages d'erreur vous disent quelle vue Django essaie de charger (et n'arrive
- pas à trouver, parce que vous n'avez pas encore écrit les vues).</p>
- <p>Il est temps d'écrire la première vue. Ouvrez le fichier
- <tt class="docutils literal"><span class="pre">monsite/polls/views.py</span></tt> et mettez-y le code Python suivant:</p>
- <pre class="literal-block">
- from django.http import HttpResponse
-
- def index(request):
- return HttpResponse("Bonjour tout le monde. Vous est dans l'index des sondages.")
- </pre>
- <p>Voilà la vue la plus simple possible. Allez dans « /polls/ » avec votre
- navigateur, et vous devriez voir votre texte.</p>
- <p>À présent, ajoutez la vue suivante. C'est un petit peu différent, parce qu'il
- prend un argument (qui, rappelez-vous, est passé depuis ce qui a été capturé par
- l'expression rationnelle dans l'URLconf):</p>
- <pre class="literal-block">
-
- def detail(request, poll_id):
- return HttpResponse("Vous consultez le sondage %s." % poll_id)
- </pre>
- <p>Jetez à oeil à votre navigateur, à « /polls/34/ ». Ça affichera l'ID que vous
- avez fournie dans l'URL.</p>
- </div>
-
- <div class="section">
- <h1><a id="crire-des-vues-qui-font-quelque-chose" name="crire-des-vues-qui-font-quelque-chose">Écrire des vues qui font quelque chose</a></h1>
- <p>Chaque vue a la responsabilité de faire l'une des deux choses suivantes :
- Retourner un objet <tt class="docutils literal"><span class="pre">HttpResponse</span></tt> renfermant le contenu de la page demandée,
- ou lever une exception telle que <tt class="docutils literal"><span class="pre">Http404</span></tt>. Le reste est pour vous.</p>
-
- <p>Votre vue peut lire ou non les enregistrements d'une base de données. Il peut
- utiliser ou non un système de template tel que celui de Django -- ou un système
- tiers de template Python. Il peut générer un fichier PDF, une sortie XML, créer
- un fichier ZIP à la volée, tout ce que vous voulez, en utilisant toutes les
- bibliothèques Python que vous désirez.</p>
- <p>Tout ce que Django veut, c'est <tt class="docutils literal"><span class="pre">HttpResponse</span></tt>. Ou une exception.</p>
- <p>Parce que c'est plus pratique, utilisons l'API de base de données propre à
- Django, que nous avons abordée dans le Tutoriel 1. Voici un premier jet de la
- vue <tt class="docutils literal"><span class="pre">index()</span></tt>, qui affiche les 5 dernières questions de sondage du système,
- séparées par des virgules, triées par date de publication:</p>
- <pre class="literal-block">
- from monsite.polls.models import Poll
- from django.http import HttpResponse
-
- def index(request):
- latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
- output = ', '.join([p.question for p in latest_poll_list])
- return HttpResponse(output)
- </pre>
- <p>Nous avons ici un problème, à savoir : Le design de la page est codée en dure
- dans la vue. Si vous voulez changer l'apparence de la page, vous devrez éditer
- ce code Python. Donc utilisons plutôt le système de template de Django pour
- la présentation des données:</p>
- <pre class="literal-block">
- from django.template import Context, loader
- from monsite.polls.models import Poll
- from django.http import HttpResponse
-
- def index(request):
- latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
- t = loader.get_template('polls/index.html')
- c = Context({
- 'latest_poll_list': latest_poll_list,
- })
- return HttpResponse(t.render(c))
-
- </pre>
- <p>Ce code charge la template appelé « polls/index.html » et lui passe un contexte.
- Le contexte est un dictionnaire indexant les objets Python selon des noms de
- variable de template.</p>
- <p>Rechargez la page. Maintenant, vous verrez une erreur:</p>
- <pre class="literal-block">
- TemplateDoesNotExist at /polls/
- polls/index.html
- </pre>
- <p>Ah. Il n'y a pas encore de template. En premier lieu, créez un répertoire,
- quelque part dans votre système de fichers, auquel Django a accès (Django
- s'exécute avec les droits de l'utilisateur qui a lancé le serveur). Cependant,
- ne les mettez pas à la racine de vos documents. Vous ne devriez probablement pas
- les rendre publics, juste par mesure de sécurité.</p>
- <p>Puis éditez <tt class="docutils literal"><span class="pre">TEMPLATE_DIRS</span></tt> dans votre <tt class="docutils literal"><span class="pre">settings.py</span></tt> pour dire à Django où
- il peut trouver les templates -- tout comme vous l'avez fait dans la section
- « Personnaliser l'apparence de l'interface d'admin » du Tutoriel 2.</p>
-
- <p>Une fois fait, créez un répertoire <tt class="docutils literal"><span class="pre">polls</span></tt> dans votre répertoire de templates.
- Dedans, créez un fichier appelé <tt class="docutils literal"><span class="pre">index.html</span></tt>. Notez que notre code
- <tt class="docutils literal"><span class="pre">loader.get_template('polls/index.html')</span></tt> ci-dessus se réfère à
- "[répertoire_de_templates]/polls/index.html" dans le système de fichiers.</p>
- <p>Placez le code suivant dans ce template:</p>
- <pre class="literal-block">
- {% if latest_poll_list %}
- <ul>
-
- {% for poll in latest_poll_list %}
- <li>{{ poll.question }}</li>
- {% endfor %}
- </ul>
- {% else %}
- <p>Aucun sondage disponnible.</p>
- {% endif %}
- </pre>
-
- <p>Chargez la page dans votre navigateur Web, et vous devriez voir une liste à puce
- contenant le sondage "Quoi de neuf" du Tutoriel 1.</p>
- <div class="section">
- <h2><a id="un-raccourci-render-to-response" name="un-raccourci-render-to-response">Un raccourci: render_to_response()</a></h2>
- <p>Il est vraiment très courant de charger un template, remplir un contexte et
- retourner un objet <tt class="docutils literal"><span class="pre">HttpResponse</span></tt> avec le résultat du rendu de la template.
- Django fournit un raccourci. Voici le vue complète de <tt class="docutils literal"><span class="pre">index()</span></tt>, réécrite:</p>
- <pre class="literal-block">
- from django.shortcuts import render_to_response
- from monsite.polls.models import Poll
-
- def index(request):
- latest_poll_list = Poll.objects.all().order_by('-pub_date')
- return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
-
- </pre>
- <p>Notez que nous n'avons plus besoin d'importer <tt class="docutils literal"><span class="pre">loader</span></tt>, <tt class="docutils literal"><span class="pre">Context</span></tt> ni
- <tt class="docutils literal"><span class="pre">HttpResponse</span></tt>.</p>
- <p>La fonction <tt class="docutils literal"><span class="pre">render_to_response()</span></tt> prend un nom de template en premier
- argument et un dictionnaire comme second argument facultatif. Il retourne un
- objet <tt class="docutils literal"><span class="pre">HttpResponse</span></tt> du template donné rendu avec le contexte donné.</p>
-
- </div>
-
- <p></div>
- <div class="section">
- <h1><a id="lever-l-erreur-404" name="lever-l-erreur-404">Lever l'erreur 404</a></h1>
- <p>À présent, abordons la vue de sondage détaillé -- la page qui affiche la
- question d'un sondage donné. Voici la vue:</p>
- <pre class="literal-block">
- from django.http import Http404</p>
- <h1>...</h1>
- <p>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})
- </pre>
- <p>Le nouveau concept ici : La vue lève l'exception <tt class="docutils literal"><span class="pre">django.http.Http404</span></tt> si un
- sondage avec l'ID demandé n'existe pas.</p>
- <div class="section">
- <h2><a id="un-raccourci-get-object-or-404" name="un-raccourci-get-object-or-404">Un raccourci : get_object_or_404()</a></h2></p>
- <p>Il est vraiment très courant d'utiliser <tt class="docutils literal"><span class="pre">get_object()</span></tt> et de déclencher
- <tt class="docutils literal"><span class="pre">Http404</span></tt> si l'objet n'existe pas. Django fournit un raccourci. Voici la vue
- <tt class="docutils literal"><span class="pre">detail()</span></tt>, réécrite:</p>
-
- <pre class="literal-block">
- from django.shortcuts import render_to_response, get_object_or_404
- # ...
- def detail(request, poll_id):
- p = get_object_or_404(Poll, pk=poll_id)
- return render_to_response('polls/detail.html', {'poll': p})
- </pre>
-
- <p>La fonction <tt class="docutils literal"><span class="pre">get_object_or_404()</span></tt> prend un modèle Django en premier argument
- et un nombre arbitaire d'arguments mot-clés, qu'elle passe à la fonction
-
- <tt class="docutils literal"><span class="pre">get_object()</span></tt> du module. Elle déclenche <tt class="docutils literal"><span class="pre">Http404</span></tt> si l'object n'existe pas.</p>
-
- <div class="admonition-philosophie admonition">
- <p class="first admonition-title">Philosophie</p>
- <p>Pourquoi utilisons-nous une fonction utilitaire <tt class="docutils literal"><span class="pre">get_object_or_404()</span></tt> au
- lieu de récupérer automatiquement les exceptions <tt class="docutils literal"><span class="pre">DoesNotExist</span></tt> de haut
- niveau, ou avoir l'API du modèle qui déclenche <tt class="docutils literal"><span class="pre">Http404</span></tt> au lieu de
-
- <tt class="docutils literal"><span class="pre">DoesNotExist</span></tt> ?</p>
- <p class="last">Parce que ça serait coupler la couche du modèle avec la couche de la vue.
- Une des règles d'or de la conception de Django est de maintenir ce
- découplage entre les différentes couches.</p>
- </div>
-
- <p>Il y a également une fonction <tt class="docutils literal"><span class="pre">get_list_or_404()</span></tt>, qui fonctionne
- similairement à <tt class="docutils literal"><span class="pre">get_object_or_404()</span></tt> -- sauf qu'elle utilise <tt class="docutils literal"><span class="pre">filter()</span></tt>
- au lieu de <tt class="docutils literal"><span class="pre">get()</span></tt>. Elle lève <tt class="docutils literal"><span class="pre">Http404</span></tt> si la liste est vide.</p>
-
- <p></div>
- </div>
- <div class="section">
- <h1><a id="crire-une-vue-404-page-non-trouv-e" name="crire-une-vue-404-page-non-trouv-e">Écrire une vue 404 (page non trouvée)</a></h1>
- <p>Lorsque vous levez une <tt class="docutils literal"><span class="pre">Http404</span></tt> à partir d'une vue, Django va charger une vue
- spéciale qui s'occupe des erreurs 404. Il la trouve en cherchant la variable
- <tt class="docutils literal"><span class="pre">handler404</span></tt>, qui est une chaîne de caractères utilisant la syntaxe Python à
- points -- le même format qui est utilisé par l'URLconf. Une vue 404 en elle-même
- n'a rien de particulier : c'est juste une vue classique.</p>
- <p>Vous n'avez normalement pas à vous soucier de l'écriture des vues 404.
- Par défaut les URLconfs ont la ligne suivante en en-tête :</p>
- <blockquote>
- from django.conf.urls.defaults import *</blockquote></p>
- <p>Cela permet de prendre en compte le paramètre <tt class="docutils literal"><span class="pre">handler404</span></tt> pour le module
- courrant. Comme vous pouvez le constater dans <tt class="docutils literal"><span class="pre">django/conf/urls/defaults.py</span></tt>,
- <tt class="docutils literal"><span class="pre">handler404</span></tt> correspond par défaut à
- <tt class="docutils literal"><span class="pre">'django.views.defaults.page_not_found'</span></tt>.</p>
-
- <p>Encore trois remarques au sujet des vues 404 :</p>
-
- <blockquote>
- <ul class="simple">
- <li>La vue 404 est aussi appelée si aucune des expressions rationnelle de
- l'URLconf ne correspond à l'adresse demandée.</li>
-
- <li>Si vous ne définissez pas votre propre vue 404 -- et utilisez celle par
- défaut, ce qui est recommandé -- vous devez quand même créer un template
- <tt class="docutils literal"><span class="pre">404.html</span></tt> à la racide de votre dossier de templates.</li>
- <li>Si <tt class="docutils literal"><span class="pre">DEBUG</span></tt> est à <tt class="docutils literal"><span class="pre">True</span></tt> (dans votre module de paramètres), votre vue
- 404 utilisera ce template pour toutes les erreurs 404.</li>
- </ul>
- </blockquote>
-
- <p></div>
- <div class="section"></p>
- <h1><a id="crire-une-vue-500-erreur-serveur" name="crire-une-vue-500-erreur-serveur">Écrire une vue 500 (erreur serveur)</a></h1>
-
- <p>De la même manière, URLconfs peut définir une <tt class="docutils literal"><span class="pre">handler500</span></tt>, qui pointe sur une
- vue appelée en cas d'erreur du serveur. Les erreurs du serveur lorsque vous avez
- des erreurs d'exécution dans le code de vos vues.</p>
-
- <p></div>
- <div class="section">
- <h1><a id="utiliser-le-syst-me-de-template" name="utiliser-le-syst-me-de-template">Utiliser le système de template</a></h1>
- <p>Revenons à notre vue <tt class="docutils literal"><span class="pre">polls.detail</span></tt>. Considérant la variable de contexte
- <tt class="docutils literal"><span class="pre">poll</span></tt>, voici le template tel qu'il pourrait être:</p>
- <pre class="literal-block"></p>
- <p><h1>{{ poll.question }}</h1>
- <ul>
- {% for choice in poll.choice_set.all %}
- <li>{{ choice.choice }}</li>
- {% endfor %}
- </ul>
- </pre>
- <p>Le système de template utilise une syntaxe par points pour accéder aux attributs
- des variables. Dans l'exemple <tt class="docutils literal"><span class="pre">{{</span> <span class="pre">poll.question</span> <span class="pre">}}</span></tt>, Django commence par
- chercher la clé <tt class="docutils literal"><span class="pre">question</span></tt> du dictionnaire <tt class="docutils literal"><span class="pre">poll</span></tt>. N'y parvenant pas, il
- essaye avec les attributs de classe -- ce qui marche dans ce cas. Si ça n'avait
- pas été le cas, il aurait essayé d'appeler la méthode <tt class="docutils literal"><span class="pre">question()</span></tt> de l'objet
- poll.</p></p>
- <p>L'appel d'une méthode se produit dans la boucle <tt class="docutils literal"><span class="pre">{%</span> <span class="pre">for</span> <span class="pre">%}</span></tt> :
- <tt class="docutils literal"><span class="pre">poll.choice_set.all</span></tt> est interprété comme le code <tt class="docutils literal"><span class="pre">poll.choice_set.all()</span></tt>,
- ce qui renvoie un iterable d'objets « Choice » ce qui est parfait pour une
- utilisation dans un tag <tt class="docutils literal"><span class="pre">{%</span> <span class="pre">for</span> <span class="pre">%}</span></tt>.</p>
-
- <p>Lisez le <a class="reference" href="http://www.djangoproject.com/documentation/templates/">guide des templates</a> pour davantage de détails sur le fonctionnement
- des templates.</p>
-
- <p></div>
- <div class="section">
- <h1><a id="simplifier-urlconfs" name="simplifier-urlconfs">Simplifier URLconfs</a></h1>
- <p>Prennons le temps de jouer un peu avec les vues et le système de templates. Lors
- de l'édition d'URLconf, vous avez dû vous rendre compte de la redondance
- présente dans le fichier:</p>
- <pre class="literal-block">
- urlpatterns = patterns('',
- (r'^polls/$', 'mysite.polls.views.index'),
- (r'^polls/(?P<poll_id>\d+)/$', 'mysite.polls.views.detail'),
- (r'^polls/(?P<poll_id>\d+)/results/$', 'mysite.polls.views.results'),
- (r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
- )</p>
- <p></pre>
- <p>Le répertoire d'accès <tt class="docutils literal"><span class="pre">mysite.polls.views</span></tt> est dans chaque URL.</p>
- <p>Étant un cas courrant, le framework URLconf possède un raccourci pour les
- préfixes communs. Vous pouvez les factoriser et les placer en premier argument
- de <tt class="docutils literal"><span class="pre">patterns()</span></tt> de la façon suivante:</p>
- <pre class="literal-block">
- urlpatterns = patterns('mysite.polls.views',
- (r'^polls/$', 'index'),
- (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
- (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
- (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'),
- )</p>
- <p></pre>
- <p>C'est identique au précédent formatage. C'est juste un peu plus propre.</p>
- </div>
- <div class="section">
- <h1><a id="d-coupler-urlconfs" name="d-coupler-urlconfs">Découpler URLconfs</a></h1>
- <p>En parlant de ça, prennons le temps de découpler les URLs de notre appli de
- sondage à partir de la configuration de notre projet Django. Les applis Django
- sont censées être « pluggables » -- ce qui signifie que chaque application peut
- être transférée sur une autre installation de Django avec le minimum de
- désagréments.</p>
- <p>Notre appli de sondage est pas mal découplée pour le moment grâce à la structure
- générée par <tt class="docutils literal"><span class="pre">python</span> <span class="pre">manage.py</span> <span class="pre">startapp</span></tt>. Une partie est néanmois liée aux
- paramètres de Django : l'URLconf.</p></p>
- <p>Nous avons édité les URLs dans <tt class="docutils literal"><span class="pre">mysite/urls.py</span></tt>, mais la conception des URLs
- d'une appli est spécifique à l'application, pas à l'installation de Django --
- déplaçons donc les URLs dans le dossier de notre appli.</p>
-
- <p>Copiez le fichier <tt class="docutils literal"><span class="pre">mysite/urls.py</span></tt> vers <tt class="docutils literal"><span class="pre">mysite/polls/urls.py</span></tt>. Puis,
- modifiez <tt class="docutils literal"><span class="pre">mysite/urls.py</span></tt> pour retirer les URLs spécifiques au sondage et
- insérez un <tt class="docutils literal"><span class="pre">include()</span></tt>:</p>
-
- <pre class="literal-block">
-
- (r'^polls/', include('mysite.polls.urls')),
- </pre>
-
- <p><tt class="docutils literal"><span class="pre">include()</span></tt>, permet simplement d'établir une référence à une autre URLconf.
- Notez l'absence de <tt class="docutils literal"><span class="pre">$</span></tt> (détection de fin de chaîne de caractère) dans
- l'expression rationnelle mais la présence d'un slash final. Lorsque Django
- rencontre un <tt class="docutils literal"><span class="pre">include()</span></tt>, il extrait tout ce qui suit l'URL détectée et
- l'envoie à l'URLconf inclus pour un traitement ultérieur.</p>
-
- <p>Voici ce qu'il se passe si un utilisateur se rend sur « /polls/34/ » avec ce
- système :</p>
-
- <ul class="simple">
- <li>Django va rencontrer <tt class="docutils literal"><span class="pre">'^polls/'</span></tt></li>
- <li>Il va enlever la partie reconnue (<tt class="docutils literal"><span class="pre">"polls/"</span></tt>) et envoyer le texte restant --
-
- <tt class="docutils literal"><span class="pre">"34/"</span></tt> -- à l'URLconf monsite.polls.urls' pour un traitement ultérieur.</li>
- </ul>
-
- <p>Maitenant que le découplage est effectué, il est nécessaire de découpler
- l'URLconf de 'monsite.polls.urls' en enlevant les préfixes « polls/ » à chaque
- ligne:</p>
-
- <pre class="literal-block">
- urlpatterns = patterns('monsite.polls.views',
- (r'^$', 'index'),
- (r'^(?P<poll_id>\d+)/$', 'detail'),
- (r'^(?P<poll_id>\d+)/results/$', 'results'),
- (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
- )
- </pre>
-
- <p>L'idée derrière <tt class="docutils literal"><span class="pre">include()</span></tt> et le découplage d'URLconf est de faciliter
- l'aspect plug-and-play des URLs. Maintenant que les sondages ont leur propre
- URLconf, ils peuvent être placés à la suite de « /polls », ou de « /fun_polls »,
- ou de « /content/polls », ou de n'importe quelle URL, et l'appli sera toujours
- fonctionnelle.</p>
-
- <p>Toute l'appli de sondage se base sur des URL relatives, non sur des URLs
- absolues.</p>
-
- <p>Lorsque vous avez assimilé l'écriture des vues, lisez la
- <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-4-conception-d-un-formulaire-et-vues-generiques/">partie 4 de ce tutoriel</a> de façon à en apprendre plus sur la génération de
- formulaires et les vues génériques.</p>
-
- <p>Vous pouvez maintenant retourner à la <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-traduction-francaise-de-la-documentation-de-django-le-framework-web-python/">page d'accueil des traductions de la
- documentation de Django</a>.</p>
-
- <p>Cette traduction correspond à la révision 3589 (post 0.95).</p>
-
- </div>
- </div>
- </article>
- <footer>
- <h6 property="schema:datePublished">— 17/06/2006</h6>
- </footer>
- </section>
- <section>
- <div>
- <h3>Articles peut-être en rapport</h3>
- <ul>
- <li><a href="/david/biologeek/archives/20060815-le-langage-de-template-django-pour-les-auteurs-de-templates/" title="Accès à Le langage de template Django : Pour les auteurs de templates">Le langage de template Django : Pour les auteurs de templates</a></li>
- <li><a href="/david/biologeek/archives/20060715-comparaison-de-turbogears-et-django-deux-frameworks-web-python/" title="Accès à Comparaison de TurboGears et Django, deux frameworks web Python">Comparaison de TurboGears et Django, deux frameworks web Python</a></li>
- <li><a href="/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-4-conception-d-un-formulaire-et-vues-generiques/" title="Accès à Rédaction de votre première appli Django, partie 4 : Conception d'un formulaire et vues génériques">Rédaction de votre première appli Django, partie 4 : Conception d'un formulaire et vues génériques</a></li>
- </ul>
- </div>
- </section>
- <section>
- <div id="comments">
- <h3>Commentaires</h3>
-
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">David</span> le <span class="comment-date" property="schema:commentTime">19/07/2006</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>Tu as laissé un morceau d'anglais dans la partie erreur 500 :-)</p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">19/07/2006</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>En effet, merci c'est corrigé :)</p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">gigi</span> le <span class="comment-date" property="schema:commentTime">04/01/2007</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>Copiez le fichier mysite/urls.py vers mysite/polls/urls.py. Puis, modifiez mysite/urls.py pour retirer les URLs spécifiques au sondage et insérez un include():<br />
- <br />
- (r'^polls/', include('mysite.polls.urls')),<br />
- <br />
- à remplacer par : <br />
- <br />
- Copiez le fichier mysite/urls.py vers mysite/polls/urls.py. Puis, modifiez mysite/urls.py comme indiquer ci-dessous<br />
- <br />
- from django.conf.urls.defaults import *<br />
- <br />
- urlpatterns = patterns('',<br />
- (r'', include('mysite.polls.urls')),<br />
- )</p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">cgasmi</span> le <span class="comment-date" property="schema:commentTime">24/05/2007</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>il y a une petite erreur de traduction:<br />
- une requête vers <a href="http://www.exemple.com/monappli/?page=3," title="http://www.exemple.com/monappli/?page=3," rel="nofollow">www.exemple.com/monappli/...</a> l'URLconf va rechercher dans /myapp/.<br />
- <br />
- /myapp/ a la place de /monappli/<br />
- <br />
- Sinon merci pour cette doc, elle m'a beaucoup aider dans mon debut avec django.</p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">Raysuken</span> le <span class="comment-date" property="schema:commentTime">26/06/2007</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>Tres bon tuto pour commercer a utiliser le framework django !!<br />
- <br />
- Merci</p>
- </div>
- </div>
-
- </div>
- </section>
-
-
- <footer>
- <nav>
- <p>
- <small>
- Je réponds quasiment toujours aux <a href="mailto:david%40larlet.fr" title="Envoyer un email">emails</a> (<a href="/david/signature/" title="Ma signature actuelle avec possibilité de chiffrement">signés</a>) et vous pouvez me rencontrer à Montréal. <span class="more-infos">N’hésitez pas à <a href="/david/log/" title="Être tenu informé des mises à jour">vous abonner</a> pour être tenu informé des publications récentes.</span>
- </small>
- </p>
- </nav>
- </footer>
-
- </div>
-
- <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
-
- <script data-no-instant>InstantClick.init()</script>
-
- </body>
- </html>
|