{"title":"Écriture de votre première application Django, 3ème partie","version":"1.9","locale":"fr","docname":"intro/tutorial03","url":"/fr/1.9/intro/tutorial03/","canonical":"https://djangodocs.dev/fr/1.9/intro/tutorial03/","summary":"Ce tutoriel commence là où le tutoriel 2 s’achève. Nous continuons l’application de sondage Web et allons nous focaliser sur la création de l’interface publique –…","html":"<h1>Écriture de votre première application Django, 3ème partie<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-3\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Ce tutoriel commence là où le <a class=\"reference internal\" href=\"/fr/1.9/intro/tutorial02/\"><span class=\"doc\">tutoriel 2</span></a> s’achève. Nous continuons l’application de sondage Web et allons nous focaliser sur la création de l’interface publique – les « vues ».</p>\n<section id=\"overview\">\n<h2>Aperçu<a class=\"heading-anchor\" href=\"#overview\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Une vue est un « type » de page Web dans votre application Django qui sert généralement à une fonction précise et possède un gabarit spécifique. Par exemple, dans une application de blog, vous pouvez avoir les vues suivantes :</p>\n<ul class=\"simple\">\n<li><p>La page d’accueil du blog – affiche quelques-uns des derniers billets.</p></li>\n<li><p>La page de « détail » d’un billet – lien permanent vers un seul billet.</p></li>\n<li><p>La page d’archives pour une année – affiche tous les mois contenant des billets pour une année donnée.</p></li>\n<li><p>La page d’archives pour un mois – affiche tous les jours contenant des billets pour un mois donné.</p></li>\n<li><p>La page d’archives pour un jour – affiche tous les billets pour un jour donné.</p></li>\n<li><p>Action de commentaire – gère l’écriture de commentaires sur un billet donné.</p></li>\n</ul>\n<p>Dans notre application de sondage, nous aurons les quatre vues suivantes :</p>\n<ul class=\"simple\">\n<li><p>La page de sommaire des questions – affiche quelques-unes des dernières questions.</p></li>\n<li><p>La page de détail d’une question – affiche le texte d’une question, sans les résultats mais avec un formulaire pour voter.</p></li>\n<li><p>La page des résultats d’une question – affiche les résultats d’une question particulière.</p></li>\n<li><p>Action de vote – gère le vote pour un choix particulier dans une question précise.</p></li>\n</ul>\n<p>Dans Django, les pages Web et les autres contenus sont générés par des vues. Chaque vue est représentée par une simple fonction Python (ou une méthode dans le cas des vues basées sur des classes). Django choisit une vue en examinant l’URL demandée (pour être précis, la partie de l’URL après le nom de domaine).</p>\n<p>Dans votre expérience sur le Web, vous avez certainement rencontré des perles comme par exemple « ME2/Sites/dirmod.asp?sid=&amp;type=gen&amp;mod=Core+Pages&amp;gid=A6CD4967199A42D9B65B1B ». Vous serez certainement rassuré en sachant que Django permet des styles d’URL bien plus élégants que cela.</p>\n<p>Un modèle d’URL est simplement la forme générale d’une URL ; par exemple : <code class=\"docutils literal notranslate\"><span class=\"pre\">/archive/&lt;année&gt;/&lt;mois&gt;/</span></code>.</p>\n<p>Pour passer de l’URL à la vue, Django utilise ce qu’on appelle des « URLconf ». Un URLconf associe des modèles d’URL (définis par des expressions régulières) à des vues.</p>\n<p>Ce tutoriel fournit des instructions de base sur l’utilisation des URLconf, et vous pouvez consultez <a class=\"reference internal\" href=\"/fr/1.9/ref/urlresolvers/#module-django.core.urlresolvers\" title=\"django.core.urlresolvers\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.core.urlresolvers</span></code></a> pour plus de détails.</p>\n</section>\n<section id=\"writing-more-views\">\n<h2>Écriture de vues supplémentaires<a class=\"heading-anchor\" href=\"#writing-more-views\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ajoutons maintenant quelques vues supplémentaires dans <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code>. Ces vues sont légèrement différentes, car elles acceptent un paramètre :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/views.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/views.py\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re looking at question </span><span class=\"si\">%s</span><span class=\"s2\">.&quot;</span> <span class=\"o\">%</span> <span class=\"n\">question_id</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">results</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;You&#39;re looking at the results of question </span><span class=\"si\">%s</span><span class=\"s2\">.&quot;</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"n\">response</span> <span class=\"o\">%</span> <span class=\"n\">question_id</span><span class=\"p\">)</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">vote</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re voting on question </span><span class=\"si\">%s</span><span class=\"s2\">.&quot;</span> <span class=\"o\">%</span> <span class=\"n\">question_id</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Liez ces nouvelles vues avec leurs URL dans le module <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.urls</span></code> en ajoutant les appels <a class=\"reference internal\" href=\"/fr/1.9/ref/urls/#django.conf.urls.url\" title=\"django.conf.urls.url\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">url()</span></code></a> suivants :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/urls.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/urls.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">url</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">views</span>\n\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"c1\"># ex: /polls/</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;index&#39;</span><span class=\"p\">),</span>\n    <span class=\"c1\"># ex: /polls/5/</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n    <span class=\"c1\"># ex: /polls/5/results/</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/results/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">results</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;results&#39;</span><span class=\"p\">),</span>\n    <span class=\"c1\"># ex: /polls/5/vote/</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/vote/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">vote</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;vote&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Ouvrez votre navigateur à l’adresse « /polls/34/ ». La méthode <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> sera exécutée et affichera l’ID fourni dans l’URL. Essayez aussi « /polls/34/results/ » et « /polls/34/vote/ », elles afficheront les pages modèles de résultats et de votes.</p>\n<p>When somebody requests a page from your website – say, « /polls/34/ », Django\nwill load the <code class=\"docutils literal notranslate\"><span class=\"pre\">mysite.urls</span></code> Python module because it’s pointed to by the\n<a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-ROOT_URLCONF\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ROOT_URLCONF</span></code></a> setting. It finds the variable named <code class=\"docutils literal notranslate\"><span class=\"pre\">urlpatterns</span></code>\nand traverses the regular expressions in order. After finding the match at\n<code class=\"docutils literal notranslate\"><span class=\"pre\">'^polls/'</span></code>, it strips off the matching text (<code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;polls/&quot;</span></code>) and sends the\nremaining text – <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;34/&quot;</span></code> – to the “polls.urls” URLconf for further\nprocessing. There it matches <code class=\"docutils literal notranslate\"><span class=\"pre\">r'^(?P&lt;question_id&gt;[0-9]+)/$'</span></code>, resulting in a\ncall to the <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> view like so:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"o\">=&lt;</span><span class=\"n\">HttpRequest</span> <span class=\"nb\">object</span><span class=\"o\">&gt;</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"o\">=</span><span class=\"s1\">&#39;34&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>La partie <code class=\"docutils literal notranslate\"><span class=\"pre\">question_id='34'</span></code> vient de <code class=\"docutils literal notranslate\"><span class=\"pre\">(?P&lt;question_id&gt;[0-9]+)</span></code>. En utilisant des parenthèses autour d’un motif, cela « capture » le texte correspondant à ce motif et l’envoie en tant que paramètre à la fonction de la vue ; le terme <code class=\"docutils literal notranslate\"><span class=\"pre\">?P&lt;question_id&gt;</span></code> définit le nom qui va être utilisé pour identifier le motif trouvé, et <code class=\"docutils literal notranslate\"><span class=\"pre\">[0-9]+</span></code> est une expression régulière pour chercher une suite de chiffres (c’est-à-dire un nombre).</p>\n<p>Comme les motifs d’URL sont des expressions régulières, il n’y a vraiment aucune limite à ce qu’ils vous permettent de faire. Et il n’y a pas besoin d’ajouter de fioritures aux URL tel que <code class=\"docutils literal notranslate\"><span class=\"pre\">.html</span></code> – sauf si vous le voulez vraiment, auquel cas vous pouvez faire quelque chose comme ça :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^polls/latest\\.html$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">),</span>\n</code></pre></div>\n<p>Mais ne le faites pas. C’est stupide.</p>\n</section>\n<section id=\"write-views-that-actually-do-something\">\n<h2>Écriture de vues qui font réellement des choses<a class=\"heading-anchor\" href=\"#write-views-that-actually-do-something\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Chaque vue est responsable de faire une des deux choses suivantes : retourner un objet <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> contenant le contenu de la page demandée, ou lever une exception, comme par exemple <a class=\"reference internal\" href=\"/fr/1.9/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a>. Le reste, c’est votre travail.</p>\n<p>Votre vue peut lire des entrées depuis une base de données, ou pas. Elle peut utiliser un système de gabarits comme celui de Django – ou un système de gabarits tiers – ou pas. Elle peut générer un fichier PDF, produire de l’XML, créer un fichier ZIP à la volée, tout ce que vous voulez, en utilisant les bibliothèques Python que vous voulez.</p>\n<p>Voilà tout ce que veut Django : <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> ou une exception.</p>\n<p>Parce que c’est pratique, nous allons utiliser l’API de base de données de Django, que nous avons vu dans le <a class=\"reference internal\" href=\"/fr/1.9/intro/tutorial02/\"><span class=\"doc\">tutoriel 2</span></a>. Voici une ébauche d’une nouvelle vue <code class=\"docutils literal notranslate\"><span class=\"pre\">index()</span></code>, qui affiche les 5 derniers sondages, séparés par des virgules et classés par date de publication :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/views.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/views.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">index</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">latest_question_list</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n    <span class=\"n\">output</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;, &#39;</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">([</span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">question_text</span> <span class=\"k\">for</span> <span class=\"n\">q</span> <span class=\"ow\">in</span> <span class=\"n\">latest_question_list</span><span class=\"p\">])</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"n\">output</span><span class=\"p\">)</span>\n\n<span class=\"c1\"># Leave the rest of the views (detail, results, vote) unchanged</span>\n</code></pre></figure>\n<p>Cependant, il y a un problème : l’allure de la page est codée en dur dans la vue. Si vous voulez changer le style de la page, vous devrez modifier votre code python. Nous allons donc utiliser le système de gabarits de Django pour séparer le style du code Python en créant un gabarit que la vue pourra utiliser.</p>\n<p>Tout d’abord, créez un répertoire nommé <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> dans votre répertoire <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>. C’est là que Django recherche les gabarits.</p>\n<p>Le paramètre <a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TEMPLATES</span></code></a> de votre projet indique comment Django va charger et produire les gabarits. Le fichier de réglages par défaut configure un moteur <code class=\"docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code> dont l’option <a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-TEMPLATES-APP_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">APP_DIRS</span></code></a> est définie à <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>. Par convention, <code class=\"docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code> recherche un sous-répertoire « templates » dans chaque application figurant dans <a class=\"reference internal\" href=\"/fr/1.9/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>.</p>\n<p>Dans le répertoire <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> que vous venez de créer, créez un autre répertoire nommé polls` dans lequel vous placez un nouveau fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">index.html</span></code>. Autrement dit, le chemin de votre gabarit doit être  <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/index.html</span></code>. Conformément au fonctionnement du chargeur de gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">app_directories</span></code> (cf. explication ci-dessus), vous pouvez désigner ce gabarit dans Django tout simplement par <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/index.html</span></code>.</p>\n<aside class=\"admonition-template-namespacing admonition\">\n<p class=\"admonition-title\">Espace de noms des gabarits</p>\n<p>Il serait aussi <em>possible</em> de placer directement nos gabarits dans <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates</span></code> (plutôt que dans un sous-répertoire <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>), mais ce serait une mauvaise idée. Django choisit le premier gabarit qu’il trouve pour un nom donné et dans le cas où vous avez un gabarit de même nom dans une <em>autre</em> application, Django ne fera pas la différence. Il faut pouvoir indiquer à Django le bon gabarit, et la manière la plus simple de faire cela est d’utiliser des espaces de noms. C’est-à-dire que nous plaçons ces gabarits dans un <em>autre</em> répertoire portant le nom de l’application.</p>\n</aside>\n<p>Insérez le code suivant dans ce gabarit :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code>polls/templates/polls/index.html</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/templates/polls/index.html\"><code><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">latest_question_list</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">question</span> <span class=\"k\">in</span> <span class=\"nv\">latest_question_list</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/polls/</span><span class=\"cp\">{{</span> <span class=\"nv\">question.id</span> <span class=\"cp\">}}</span><span class=\"s\">/&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>No polls are available.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></figure>\n<p>Mettons maintenant à jour notre vue <code class=\"docutils literal notranslate\"><span class=\"pre\">index</span></code> dans <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/views.py</span></code> pour qu’elle utilise le template :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/views.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/views.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">loader</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">index</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">latest_question_list</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n    <span class=\"n\">template</span> <span class=\"o\">=</span> <span class=\"n\">loader</span><span class=\"o\">.</span><span class=\"n\">get_template</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls/index.html&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">:</span> <span class=\"n\">latest_question_list</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"n\">template</span><span class=\"o\">.</span><span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">))</span>\n</code></pre></figure>\n<p>Ce code charge le gabarit appelé <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/index.html</span></code> et lui fournit un contexte. Ce contexte est un dictionnaire qui fait correspondre des objets Python à des noms de variables de gabarit.</p>\n<p>Chargez la page en appelant l’URL « /polls/ » dans votre navigateur et vous devriez voir une liste à puces contenant la question « What’s up » du <a class=\"reference internal\" href=\"/fr/1.9/intro/tutorial02/\"><span class=\"doc\">tutoriel 2</span></a>. Le lien pointe vers la page de détail de la question.</p>\n<section id=\"a-shortcut-render\">\n<h3>Un raccourci : <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.render\" title=\"django.shortcuts.render\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render()</span></code></a><a class=\"heading-anchor\" href=\"#a-shortcut-render\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il est très courant de charger un gabarit, remplir un contexte et renvoyer un objet <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> avec le résultat du gabarit\ninterprété. Django fournit un raccourci. Voici la vue <code class=\"docutils literal notranslate\"><span class=\"pre\">index()</span></code> complète, réécrite :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/views.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/views.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">index</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">latest_question_list</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">order_by</span><span class=\"p\">(</span><span class=\"s1\">&#39;-pub_date&#39;</span><span class=\"p\">)[:</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n    <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;latest_question_list&#39;</span><span class=\"p\">:</span> <span class=\"n\">latest_question_list</span><span class=\"p\">}</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls/index.html&#39;</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Notez qu’une fois que nous avons fait ceci dans toutes nos vues, nous n’avons plus à importer <a class=\"reference internal\" href=\"/fr/1.9/topics/templates/#module-django.template.loader\" title=\"django.template.loader\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">loader</span></code></a> et <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> (il faut conserver <code class=\"docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code> tant que les méthodes initiales pour <code class=\"docutils literal notranslate\"><span class=\"pre\">detail</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">results</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">vote</span></code> sont présentes).</p>\n<p>La fonction <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.render\" title=\"django.shortcuts.render\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render()</span></code></a> prend comme premier paramètre l’objet requête, un nom de gabarit comme deuxième paramètre et un dictionnaire comme troisième paramètre facultatif. Elle retourne un objet <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> composé par le gabarit interprété avec le contexte donné.</p>\n</section>\n</section>\n<section id=\"raising-a-404-error\">\n<h2>Les erreurs 404<a class=\"heading-anchor\" href=\"#raising-a-404-error\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Attaquons-nous maintenant à la vue du détail d’une question – la page qui affiche le texte de la question pour un sondage donné. Voici la vue :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/views.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/views.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Http404</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n<span class=\"c1\"># ...</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">question_id</span><span class=\"p\">)</span>\n    <span class=\"k\">except</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">DoesNotExist</span><span class=\"p\">:</span>\n        <span class=\"k\">raise</span> <span class=\"n\">Http404</span><span class=\"p\">(</span><span class=\"s2\">&quot;Question does not exist&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls/detail.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;question&#39;</span><span class=\"p\">:</span> <span class=\"n\">question</span><span class=\"p\">})</span>\n</code></pre></figure>\n<p>Le nouveau concept ici : la vue lève une exception de type <a class=\"reference internal\" href=\"/fr/1.9/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> si une question avec l’ID demandé n’existe pas.</p>\n<p>Nous parlerons un peu plus tard de ce que pourriez mettre dans le gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/detail.html</span></code>, mais si vous voulez avoir rapidement un exemple qui fonctionne, écrivez simplement ceci :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code>polls/templates/polls/detail.html</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/templates/polls/detail.html\"><code><span class=\"cp\">{{</span> <span class=\"nv\">question</span> <span class=\"cp\">}}</span>\n</code></pre></figure>\n<p>et vous obtiendrez un résultat élémentaire.</p>\n<section id=\"a-shortcut-get-object-or-404\">\n<h3>Un raccourci : <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a><a class=\"heading-anchor\" href=\"#a-shortcut-get-object-or-404\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Il est très courant d’utiliser <a class=\"reference internal\" href=\"/fr/1.9/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a> et de lever une exception <a class=\"reference internal\" href=\"/fr/1.9/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> si l’objet n’existe pas. Django fournit un raccourci. Voici la vue <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> réécrite :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/views.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/views.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">get_object_or_404</span><span class=\"p\">,</span> <span class=\"n\">render</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n<span class=\"c1\"># ...</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">detail</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">question_id</span><span class=\"p\">):</span>\n    <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">get_object_or_404</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">question_id</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls/detail.html&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;question&#39;</span><span class=\"p\">:</span> <span class=\"n\">question</span><span class=\"p\">})</span>\n</code></pre></figure>\n<p>La fonction <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a> prend un modèle Django comme premier paramètre et un nombre arbitraire de paramètres mots-clés, qu’il transmet à la méthode <a class=\"reference internal\" href=\"/fr/1.9/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a> du gestionnaire du modèle. Elle lève une exception <a class=\"reference internal\" href=\"/fr/1.9/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> si l’objet n’existe pas.</p>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">Philosophie</p>\n<p>Pourquoi utiliser une fonction auxiliaire <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a> plutôt que d’intercepter automatiquement une exception <a class=\"reference internal\" href=\"/fr/1.9/ref/exceptions/#django.core.exceptions.ObjectDoesNotExist\" title=\"django.core.exceptions.ObjectDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ObjectDoesNotExist</span></code></a> à un plus haut niveau, ou laisser l’API modèle lever une exception <a class=\"reference internal\" href=\"/fr/1.9/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> à la place de <a class=\"reference internal\" href=\"/fr/1.9/ref/exceptions/#django.core.exceptions.ObjectDoesNotExist\" title=\"django.core.exceptions.ObjectDoesNotExist\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ObjectDoesNotExist</span></code></a> ?</p>\n<p>Parce que cela couplerait la couche de gestion des modèles à la couche de vue. Un des buts principaux de la conception de Django et de garder un couplage le plus faible possible. Un peu de couplage contrôlé est introduit dans le module <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#module-django.shortcuts\" title=\"django.shortcuts: Convenience shortcuts that span multiple levels of Django's MVC stack.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.shortcuts</span></code></a>.</p>\n</aside>\n<p>Il y a aussi une fonction <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.get_list_or_404\" title=\"django.shortcuts.get_list_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_list_or_404()</span></code></a>, qui fonctionne comme <a class=\"reference internal\" href=\"/fr/1.9/topics/http/shortcuts/#django.shortcuts.get_object_or_404\" title=\"django.shortcuts.get_object_or_404\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">get_object_or_404()</span></code></a>, sauf qu’elle utilise <a class=\"reference internal\" href=\"/fr/1.9/ref/models/querysets/#django.db.models.query.QuerySet.filter\" title=\"django.db.models.query.QuerySet.filter\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">filter()</span></code></a> au lieu de la méthode <a class=\"reference internal\" href=\"/fr/1.9/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a>. Elle lève une exception <a class=\"reference internal\" href=\"/fr/1.9/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a> si la liste est vide.</p>\n</section>\n</section>\n<section id=\"use-the-template-system\">\n<h2>Utilisation du système de gabarits<a class=\"heading-anchor\" href=\"#use-the-template-system\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Revenons à la vue <code class=\"docutils literal notranslate\"><span class=\"pre\">detail()</span></code> de notre application de sondage. Étant donné la variable de contexte <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code>, voici à quoi le gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/detail.html</span></code> pourrait ressembler :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code>polls/templates/polls/detail.html</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/templates/polls/detail.html\"><code><span class=\"p\">&lt;</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">choice</span> <span class=\"k\">in</span> <span class=\"nv\">question.choice_set.all</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">choice.choice_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">ul</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>Le système de gabarits utilise une syntaxe d’accès aux attributs de variables à l’aide de points. Dans cet exemple avec <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">question.question_text</span> <span class=\"pre\">}}</span></code>, Django commence par rechercher un dictionnaire dans l’objet <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code>. En cas d’échec, il cherche un attribut – qui fonctionne dans ce cas. Si la recherche d’attribut n’avait pas fonctionné, Django aurait essayé une recherche d’index sur une liste.</p>\n<p>L’appel de méthode a lieu dans la boucle <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">for</span> <span class=\"pre\">%}</span></code></a> : <code class=\"docutils literal notranslate\"><span class=\"pre\">question.choice_set.all</span></code> est interprété comme le code Python <code class=\"docutils literal notranslate\"><span class=\"pre\">question.choice_set.all()</span></code>, qui renvoie un itérable d’objets <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> et qui convient pour l’utilisation de la balise <a class=\"reference internal\" href=\"/fr/1.9/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">for</span> <span class=\"pre\">%}</span></code></a>.</p>\n<p>Voir le <a class=\"reference internal\" href=\"/fr/1.9/topics/templates/\"><span class=\"doc\">guide des gabarits</span></a> pour plus d’informations sur les gabarits.</p>\n</section>\n<section id=\"removing-hardcoded-urls-in-templates\">\n<h2>Suppression des URL codés en dur dans les gabarits<a class=\"heading-anchor\" href=\"#removing-hardcoded-urls-in-templates\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Rappelez-vous, lorsque nous avons ajouté le lien vers la question dans le gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/index.html</span></code>, le lien a été partiellement codé en dur comme ceci :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/polls/</span><span class=\"cp\">{{</span> <span class=\"nv\">question.id</span> <span class=\"cp\">}}</span><span class=\"s\">/&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Le problème de cette approche codée en dur et fortement couplée est qu’il devient fastidieux de modifier les URL dans des projets qui ont beaucoup de gabarits. Cependant, comme vous avez défini le paramètre « name » dans les fonctions <a class=\"reference internal\" href=\"/fr/1.9/ref/urls/#django.conf.urls.url\" title=\"django.conf.urls.url\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">url()</span></code></a> du module <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.urls</span></code>, vous pouvez supprimer la dépendance en chemins d’URL spécifiques définis dans les configurations d’URL en utilisant la balise de gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">url</span> <span class=\"pre\">%}</span></code> :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>Le principe de ce fonctionnement est que l’URL est recherchée dans les définitions du module <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.urls</span></code>. Ci-dessous, vous pouvez voir exactement où le nom d’URL de « detail » est défini :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"o\">...</span>\n<span class=\"c1\"># the &#39;name&#39; value as called by the {% url %} template tag</span>\n<span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n<span class=\"o\">...</span>\n</code></pre></div>\n<p>Si vous souhaitez modifier l’URL de détail des sondages, par exemple sur le modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/specifics/12/</span></code>, il suffit de faire la modification dans <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code> au lieu de devoir toucher au contenu du ou des gabarits :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"o\">...</span>\n<span class=\"c1\"># added the word &#39;specifics&#39;</span>\n<span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^specifics/(?P&lt;question_id&gt;[0-9]+)/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n<span class=\"o\">...</span>\n</code></pre></div>\n</section>\n<section id=\"namespacing-url-names\">\n<h2>Espaces de noms et noms d’URL<a class=\"heading-anchor\" href=\"#namespacing-url-names\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Le projet du tutoriel ne contient qu’une seule application, <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>. Dans des projets Django réels, il peut y avoir cinq, dix, vingt applications ou plus. Comment Django arrive-t-il à différencier les noms d’URL entre elles ? Par exemple, l’application <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> possède une vue <code class=\"docutils literal notranslate\"><span class=\"pre\">detail</span></code> et il se peut tout à fait qu’une autre application du même projet en possède aussi une. Comment peut-on indiquer à Django quelle vue d’application il doit appeler pour une URL lors de l’utilisation de la balise de gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">url</span> <span class=\"pre\">%}</span></code> ?</p>\n<p>La réponse est donnée par l’ajout d’espaces de noms à votre configuration d’URL. Dans le fichier <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/urls.py</span></code>, ajoutez une variable <code class=\"docutils literal notranslate\"><span class=\"pre\">app_name</span></code> pour définir l’espace de nom de l’application :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/urls.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/urls.py\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">url</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">views</span>\n\n<span class=\"n\">app_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;polls&#39;</span>\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">index</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;index&#39;</span><span class=\"p\">),</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">detail</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;detail&#39;</span><span class=\"p\">),</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/results/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">results</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;results&#39;</span><span class=\"p\">),</span>\n    <span class=\"n\">url</span><span class=\"p\">(</span><span class=\"sa\">r</span><span class=\"s1\">&#39;^(?P&lt;question_id&gt;[0-9]+)/vote/$&#39;</span><span class=\"p\">,</span> <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">vote</span><span class=\"p\">,</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;vote&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Modifiez maintenant la partie suivante du gabarit polls/index.html` :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code>polls/templates/polls/index.html</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/templates/polls/index.html\"><code><span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>pour qu’elle pointe vers la vue « detail » à l’espace de nom correspondant :</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code>polls/templates/polls/index.html</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/templates/polls/index.html\"><code><span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;polls:detail&#39;</span> <span class=\"nv\">question.id</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">question.question_text</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p>Lorsque vous êtes à l’aise avec l’écriture des vues, lisez la <a class=\"reference internal\" href=\"/fr/1.9/intro/tutorial04/\"><span class=\"doc\">partie 4 de ce tutoriel</span></a> pour apprendre la gestion de formulaires simples et les vues génériques.</p>\n</section>","rootId":"writing-your-first-django-app-part-3","toc":[{"title":"Aperçu","anchor":"overview","children":[]},{"title":"Écriture de vues supplémentaires","anchor":"writing-more-views","children":[]},{"title":"Écriture de vues qui font réellement des choses","anchor":"write-views-that-actually-do-something","children":[{"title":"Un raccourci : render()","anchor":"a-shortcut-render","children":[]}]},{"title":"Les erreurs 404","anchor":"raising-a-404-error","children":[{"title":"Un raccourci : get_object_or_404()","anchor":"a-shortcut-get-object-or-404","children":[]}]},{"title":"Utilisation du système de gabarits","anchor":"use-the-template-system","children":[]},{"title":"Suppression des URL codés en dur dans les gabarits","anchor":"removing-hardcoded-urls-in-templates","children":[]},{"title":"Espaces de noms et noms d’URL","anchor":"namespacing-url-names","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"Premiers pas","url":"/fr/1.9/intro/"}],"prev":{"docname":"intro/tutorial02","title":"Écriture de votre première application Django, 2ème partie","url":"/fr/1.9/intro/tutorial02/"},"next":{"docname":"intro/tutorial04","title":"Écriture de votre première application Django, 4ème partie","url":"/fr/1.9/intro/tutorial04/"},"formats":{"html":"/fr/1.9/intro/tutorial03/","markdown":"/fr/1.9/intro/tutorial03.md","json":"/fr/1.9/intro/tutorial03.json"},"source":"https://github.com/django/django/blob/stable/1.9.x/docs/intro/tutorial03.txt","official":"https://docs.djangoproject.com/fr/1.9/intro/tutorial03/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","fr","ja","id","pt-br","es"]}