Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. <!doctype html>
  2. <html lang=fr>
  3. <head>
  4. <!-- Always define the charset before the title -->
  5. <meta charset=utf-8>
  6. <title>Rédaction de votre première appli Django, partie 4 : Conception d&#39;un formulaire et vues génériques — Biologeek — David Larlet</title>
  7. <!-- 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) -->
  8. <meta name="viewport" content="width=device-width, initial-scale=1"/>
  9. <!-- Fake favicon, to avoid extra request to the server -->
  10. <link rel="icon" href="data:;base64,iVBORw0KGgo=">
  11. <link type="application/atom+xml" rel="alternate" title="Feed" href="/david/log/" />
  12. <link rel="manifest" href="/manifest.json">
  13. <link rel="stylesheet" href="/static/david/css/larlet-david-_J6Rv.css" data-instant-track />
  14. <noscript>
  15. <style type="text/css">
  16. /* Otherwise fonts are loaded by JS for faster initial rendering. See scripts at the bottom. */
  17. body {
  18. font-family: 'EquityTextB', serif;
  19. }
  20. h1, h2, h3, h4, h5, h6, time, nav a, nav a:link, nav a:visited {
  21. font-family: 'EquityCapsB', sans-serif;
  22. font-variant: normal;
  23. }
  24. </style>
  25. </noscript>
  26. <!-- Canonical URL for SEO purposes -->
  27. <link rel="canonical" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-4-conception-d-un-formulaire-et-vues-generiques">
  28. </head>
  29. <body>
  30. <div>
  31. <header>
  32. <nav>
  33. <p>
  34. <small>
  35. 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>.
  36. </small>
  37. </p>
  38. </nav>
  39. </header>
  40. <section>
  41. <h1 property="schema:name">Rédaction de votre première appli Django, partie 4 : Conception d&#39;un formulaire et vues génériques</h1>
  42. <article typeof="schema:BlogPosting">
  43. <div property="schema:articleBody">
  44. <img src="/static/david/biologeek/images/logos/django.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
  45. <p>Ce tutoriel commence là où le <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique/">Tutoriel 3</a> s'est achevé. Nous continuons notre
  46. application de sondage en ligne et allons nous intéresser à la génération d'un
  47. formulaire simple et au ré-arrangement de notre code.</p>
  48. <div class="section">
  49. <h1><a id="g-n-rer-un-formulaire-simple" name="g-n-rer-un-formulaire-simple">Générer un formulaire simple</a></h1>
  50. <p>Commençons par mettre à jour notre template de détail de sondage issu du dernier
  51. tutoriel de façon à ce que le template contienne un élement HTML <tt class="docutils literal"><span class="pre">&lt;form&gt;</span></tt>:</p>
  52. <pre class="literal-block">
  53. &lt;h1&gt;{{ poll.question }}&lt;/h1&gt;
  54. {% if error_message %}&lt;p&gt;&lt;strong&gt;{{ error_message }}&lt;/strong&gt;&lt;/p&gt;{% endif %}
  55. &lt;form action=&quot;/polls/{{ poll.id }}/vote/&quot; method=&quot;post&quot;&gt;
  56. {% for choice in poll.choice_set.all %}
  57. &lt;input type=&quot;radio&quot; name=&quot;choice&quot; id=&quot;choice{{ forloop.counter }}&quot; value=&quot;{{ choice.id }}&quot; /&gt;
  58. &lt;label for=&quot;choice{{ forloop.counter }}&quot;&gt;{{ choice.choice }}&lt;/label&gt;&lt;br /&gt;
  59. {% endfor %}
  60. &lt;input type=&quot;submit&quot; value=&quot;Voter&quot; /&gt;
  61. &lt;/form&gt;
  62. </pre>
  63. <p>Un bref rappel :</p>
  64. <blockquote>
  65. <ul class="simple">
  66. <li>Le template ci-dessus affiche un bouton radio pour chaque choix du sondage.
  67. La valeur <tt class="docutils literal"><span class="pre">value</span></tt> de chaque bouton radio est associée à l'ID de chaque choix.
  68. Le nom <tt class="docutils literal"><span class="pre">name</span></tt> de chaque bouton radio est <tt class="docutils literal"><span class="pre">&quot;choice&quot;</span></tt>. Cela signifie que
  69. lorsque quelqu'un sélectionne l'un des boutons radio et soumet
  70. le formulaire, il envoie la donnée de type POST <tt class="docutils literal"><span class="pre">choice=3</span></tt>. C'est un
  71. formulaire HTML 101.</li>
  72. <li>Nous avons assigné l'<tt class="docutils literal"><span class="pre">action</span></tt> du formulaire à
  73. <tt class="docutils literal"><span class="pre">/polls/{{</span> <span class="pre">poll.id</span> <span class="pre">}}/vote/</span></tt>, et nous avons mis <tt class="docutils literal"><span class="pre">method=&quot;post&quot;</span></tt>.
  74. L'utilisation de <tt class="docutils literal"><span class="pre">method=&quot;post&quot;</span></tt> (au contraire de <tt class="docutils literal"><span class="pre">method=&quot;get&quot;</span></tt>) est
  75. très importante, car le fait de soumettre ce formulaire va être à l'origine
  76. d'une modification des données du côté du serveur. À chaque fois que vous
  77. créez un formulaire qui modifie des données sur le serveur, utilisez
  78. <tt class="docutils literal"><span class="pre">method=&quot;post&quot;</span></tt>. Cet adage n'est pas spécifique à Django, ce sont juste
  79. de bonnes pratiques de développement web.</li>
  80. </ul>
  81. </blockquote>
  82. <p>À présent, créons une vue Django qui récupère les données soumises et fait
  83. quelque chose avec. Rappelez-vous, dans le <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique/">Tutoriel 3</a>, nous avons créé une
  84. URLconf pour l'application de sondage qui incluait cette ligne:</p>
  85. <pre class="literal-block">
  86. (r'^(?P&lt;poll_id&gt;\d+)/vote/$', 'monsite.polls.views.vote'),
  87. </pre>
  88. <p>Donc créons une fonction <tt class="docutils literal"><span class="pre">vote()</span></tt> dans <tt class="docutils literal"><span class="pre">monsite/polls/views.py</span></tt>:</p>
  89. <pre class="literal-block">
  90. from django.shortcuts import get_object_or_404, render_to_response
  91. from django.http import HttpResponseRedirect
  92. from monsite.polls.models import Choice, Poll
  93. # ...
  94. def vote(request, poll_id):
  95. p = get_object_or_404(Poll, pk=poll_id)
  96. try:
  97. selected_choice = p.choice_set.get(pk=request.POST['choice'])
  98. except (KeyError, Choice.DoesNotExist):
  99. # Réaffiche le formulaire de vote.
  100. return render_to_response('polls/detail.html', {
  101. 'poll': p,
  102. 'error_message': &quot;Vous n'avez pas sélectionné de choix.&quot;,
  103. })
  104. else:
  105. selected_choice.votes += 1
  106. selected_choice.save()
  107. # Retourne toujours un HttpResponseRedirect après validation
  108. # des données POST. Ceci empèche que les données soient postées
  109. # deux fois si l'utilisateur clique sur le bouton Précédent.
  110. return HttpResponseRedirect('/polls/%s/results/' % p.id)
  111. </pre>
  112. <p>Ce code inclus des parties que nous n'avons pas encore étudiées dans ce tutoriel :</p>
  113. <blockquote>
  114. <ul>
  115. <li><p class="first"><tt class="docutils literal"><span class="pre">request.POST</span></tt> est un objet de type dictionnaire qui vous laisse accéder
  116. aux données soumises avec les mots-clé. Dans notre cas,
  117. <tt class="docutils literal"><span class="pre">request.POST['choice']</span></tt> retourne l'ID du choix sélectionné, sous forme
  118. de chaîne de caractères. Les valeurs issues de <tt class="docutils literal"><span class="pre">request.POST</span></tt> sont
  119. toujours des chaînes de caractères.</p>
  120. <p>Notez que Django vous permet aussi d'accéder via <tt class="docutils literal"><span class="pre">request.GET</span></tt> aux
  121. données de type GET de la même façon -- mais nous utilisons explicitement
  122. <tt class="docutils literal"><span class="pre">request.POST</span></tt> dans notre code, pour nous assurer que la modification des
  123. données se fasse uniquement par un appel à POST.</p>
  124. </li>
  125. <li><p class="first"><tt class="docutils literal"><span class="pre">request.POST['choice']</span></tt> déclenchera une <tt class="docutils literal"><span class="pre">KeyError</span></tt> si <tt class="docutils literal"><span class="pre">choice</span></tt> n'a pas
  126. été obtenu par des données de type POST. Le code ci-dessus vérifie les
  127. <tt class="docutils literal"><span class="pre">KeyError</span></tt> et réaffiche le formulaire de sondage avec un message
  128. d'erreur si <tt class="docutils literal"><span class="pre">choice</span></tt> n'a pas été donné.</p>
  129. </li>
  130. <li><p class="first">Après avoir incrémenté le compteur associé au choix soumis, le script
  131. retourne une <tt class="docutils literal"><span class="pre">HttpResponseRedirect</span></tt> à la place du <tt class="docutils literal"><span class="pre">HttpResponse</span></tt>
  132. habituel. <tt class="docutils literal"><span class="pre">HttpResponseRedirect</span></tt> prend un seul argument : l'URL
  133. vers laquelle l'utilisateur va être redirigé. Vous pouvez omettre de
  134. mentionner le « <a class="reference" href="http://">http://</a> » et le nom de domaine quand cela est possible.
  135. Cela permet à votre appli d'être portable sur différents domaines.</p>
  136. <p>Comme le commentaire Python le souligne, vous devez toujours retourner une
  137. <tt class="docutils literal"><span class="pre">HttpResponseRedirect</span></tt> après avoir traité une donnée de type POST avec
  138. succès. Cet adage n'est pas spécifique à Django, c'est juste une bonne
  139. pratique de développement web.</p>
  140. </li>
  141. </ul>
  142. </blockquote>
  143. <p>Comme il est mentionné dans le Tutoriel 3, <tt class="docutils literal"><span class="pre">request</span></tt> est un objet
  144. <tt class="docutils literal"><span class="pre">HTTPRequest</span></tt>. Pour en savoir plus au sujet des objets <tt class="docutils literal"><span class="pre">HTTPRequest</span></tt>, lisez
  145. la <a class="reference" href="http://www.djangoproject.com/documentation/request_response/">documentation sur les requêtes et réponses</a>.</p>
  146. <p>Après qu'un vote ait été effectué dans un sondage, la vue <tt class="docutils literal"><span class="pre">vote()</span></tt> redirige
  147. vers la page de résultats du sondage. Écrivons cette vue:</p>
  148. <pre class="literal-block">
  149. def results(request, poll_id):
  150. p = get_object_or_404(Poll, pk=poll_id)
  151. return render_to_response('polls/results.html', {'poll': p})
  152. </pre>
  153. <p>C'est presque la même que la vue <tt class="docutils literal"><span class="pre">detail()</span></tt> du <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique/">Tutoriel 3</a>. La seule
  154. différence est le nom du template. Nous nous occuperons de la redondance plus
  155. tard.</p>
  156. <p>Maintenant, créons un template <tt class="docutils literal"><span class="pre">results.html</span></tt>:</p>
  157. <pre class="literal-block">
  158. &lt;h1&gt;{{ poll.question }}&lt;/h1&gt;
  159. &lt;ul&gt;
  160. {% for choice in poll.choice_set.all %}
  161. &lt;li&gt;{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}&lt;/li&gt;
  162. {% endfor %}
  163. &lt;/ul&gt;
  164. </pre>
  165. <p>À présent, rendez vous à l'adresse <tt class="docutils literal"><span class="pre">/polls/1/</span></tt> dans votre navigateur et
  166. soumettez un vote. Vous devriez voir une page de résultats qui est mise à
  167. jour à chacun de vos votes. Si vous soumettez le formulaire sans avoir spécifié
  168. de choix, vous devriez observer le message d'erreur.</p>
  169. </div>
  170. <div class="section">
  171. <h1><a id="utilisez-les-vues-g-n-riques-moins-il-y-a-de-code-mieux-c-est" name="utilisez-les-vues-g-n-riques-moins-il-y-a-de-code-mieux-c-est">Utilisez les vues génériques : Moins il y a de code mieux c'est</a></h1>
  172. <p>Les vues <tt class="docutils literal"><span class="pre">detail()</span></tt> (du <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique/">Tutoriel 3</a>) et <tt class="docutils literal"><span class="pre">results()</span></tt> sont ridiculeusement
  173. simples -- et, comme nous l'avons signalé plus haut, redondantes. La vue
  174. <tt class="docutils literal"><span class="pre">index()</span></tt> (du <a class="reference" href="https://larlet.fr/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique/">Tutoriel 3</a> aussi), qui affiche une liste de sondages, est
  175. similaire.</p>
  176. <p>Ces vues correspondent à des cas courants de développement Web basic : récupérer
  177. des données de la base de données en fonction d'un paramètre passé dans l'URL,
  178. charger un template et retourner le template complété. Comme c'est si courant,
  179. Django dispose d'un raccourci, baptisé le système des « vues génériques ».</p>
  180. <p>Les vues génériques fournissent une couche d'abstraction tellement importante que
  181. vous n'avez même pas besoin de rédiger du code Python pour écrire votre appli.</p>
  182. <p>Convertissons notre application de sondage en utilisant le système des vues
  183. génériques, nous allons ainsi pouvoir supprimer une bonne partie du code que
  184. nous avons écrit précédemment. Il suffit de quelques étapes pour réaliser la
  185. conversion.</p>
  186. <div class="admonition-pourquoi-ce-r-arrangement-du-code admonition">
  187. <p class="first admonition-title">Pourquoi ce ré-arrangement du code ?</p>
  188. <p class="last">Géneralement, quand vous allez écrire une application Django, vous allez
  189. évaluer si les vues génériques sont une bonne solution à votre problème, et
  190. vous allez les utiliser dès le début sans avoir à refactoriser votre code en
  191. plein développement. Mais ce tutoriel s'est intentionnellement focalisé sur
  192. l'écriture de vues « de manière hardue » jusqu'à présent, de façon à ce que
  193. vous preniez conscience des concepts généraux.</p>
  194. </div>
  195. <p>Premièrement, éditez votre fichier d'URLconf polls/urls.py. Il
  196. devrait ressembler à ça, d'après les tutoriaux précédents:</p>
  197. <pre class="literal-block">
  198. from django.conf.urls.defaults import *
  199. urlpatterns = patterns('monsite.polls.views',
  200. (r'^$', 'index'),
  201. (r'^(?P&lt;poll_id&gt;\d+)/$', 'detail'),
  202. (r'^(?P&lt;poll_id&gt;\d+)/results/$', 'results'),
  203. (r'^(?P&lt;poll_id&gt;\d+)/vote/$', 'vote'),
  204. )
  205. </pre>
  206. <p>Faites le ressembler à:</p>
  207. <pre class="literal-block">
  208. from django.conf.urls.defaults import *
  209. from monsite.polls.models import Poll
  210. info_dict = {
  211. 'queryset': Poll.objects.all(),
  212. }
  213. urlpatterns = patterns('',
  214. (r'^$', 'django.views.generic.list_detail.object_list', info_dict),
  215. (r'^(?P&lt;object_id&gt;\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict),
  216. (r'^(?P&lt;object_id&gt;\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html')),
  217. (r'^(?P&lt;poll_id&gt;\d+)/vote/$', 'monsite.polls.views.vote'),
  218. )
  219. </pre>
  220. <p>Nous utilisons ici deux vues génériques : <tt class="docutils literal"><span class="pre">object_list</span></tt> et <tt class="docutils literal"><span class="pre">object_detail</span></tt>.
  221. Respectivement, ces deux vues rendent abstraits les concepts « d'affichage d'une
  222. liste d'objets » et « d'affichage d'une page de détails pour un type particulier
  223. d'objet ».</p>
  224. <blockquote>
  225. <ul class="simple">
  226. <li>Chaque vue générique a besoin de connaître sur quelles données est-ce
  227. qu'elle va agir. Ces données sont fournies grâce à un dictionnaire. La
  228. clé <tt class="docutils literal"><span class="pre">queryset</span></tt> de ce dictionnaire pointe sur la liste d'objets qui doit
  229. être manipulée par la vue générique.</li>
  230. <li>La vue générique <tt class="docutils literal"><span class="pre">object_detail</span></tt> attend la valeur ID issue de l'URL qui
  231. doit être appelée <tt class="docutils literal"><span class="pre">&quot;object_id&quot;</span></tt>, nous avons donc changé <tt class="docutils literal"><span class="pre">poll_id</span></tt> en
  232. <tt class="docutils literal"><span class="pre">object_id</span></tt> pour la vue générique.</li>
  233. </ul>
  234. </blockquote>
  235. <p>Par défaut, la vue générique <tt class="docutils literal"><span class="pre">object_detail</span></tt> utilise un template appelé
  236. <tt class="docutils literal"><span class="pre">&lt;nom_appli&gt;/&lt;nom_module&gt;_detail.html</span></tt>. Dans notre cas, ce sera le template
  237. appelé <tt class="docutils literal"><span class="pre">&quot;polls/poll_detail.html&quot;</span></tt>. Donc, renommons <tt class="docutils literal"><span class="pre">polls/detail.html</span></tt> en
  238. <tt class="docutils literal"><span class="pre">polls/poll_detail.html</span></tt>, et changeons la ligne <tt class="docutils literal"><span class="pre">render_to_response()</span></tt> en
  239. <tt class="docutils literal"><span class="pre">vote()</span></tt>.</p>
  240. <p>De façon similaire, la vue générique <tt class="docutils literal"><span class="pre">object_list</span></tt> utilise un template appelé
  241. <tt class="docutils literal"><span class="pre">&lt;nom_appli&gt;/&lt;nom_module&gt;_list.html</span></tt>. Donc, renommons <tt class="docutils literal"><span class="pre">polls/index.html</span></tt> en
  242. <tt class="docutils literal"><span class="pre">polls/poll_list.html</span></tt>.</p>
  243. <p>Puisque nous avons plus d'une entrée dans l'URLconf qui
  244. utilisent <tt class="docutils literal"><span class="pre">object_detail</span></tt> pour l'application de sondage, nous spécifions
  245. manuellement un nom de template pour la vue des résultats :
  246. <tt class="docutils literal"><span class="pre">template_name='polls/results.html'</span></tt>. Sinon, les deux vues auraient utilisé le
  247. même template. Notez l'utilisation de <tt class="docutils literal"><span class="pre">dict()</span></tt> pour retourner un dictionnaire
  248. modifié à la place.</p>
  249. <p>Dans les tutoriels précédents, les templates sont utilisés dans un contexte
  250. contenant les variables <tt class="docutils literal"><span class="pre">poll</span></tt> et <tt class="docutils literal"><span class="pre">latest_poll_list</span></tt>. Ici, les vues
  251. génériques nécessitent d'avoir les variables contextuelles <tt class="docutils literal"><span class="pre">object</span></tt> et
  252. <tt class="docutils literal"><span class="pre">object_list</span></tt>. Éditez vos templates et modifiez chaque référence à
  253. <tt class="docutils literal"><span class="pre">latest_poll_list</span></tt> par <tt class="docutils literal"><span class="pre">object_list</span></tt>, et chaque référence à <tt class="docutils literal"><span class="pre">poll</span></tt> par
  254. <tt class="docutils literal"><span class="pre">object</span></tt>.</p>
  255. <p>Vous pouvez maintenant supprimer les vues <tt class="docutils literal"><span class="pre">index()</span></tt>, <tt class="docutils literal"><span class="pre">detail()</span></tt> et
  256. <tt class="docutils literal"><span class="pre">results()</span></tt> de <tt class="docutils literal"><span class="pre">polls/views.py</span></tt>. Nous n'en avons plus besoin -- elles ont
  257. été remplacées par les vues génériques.</p>
  258. <p>La vue <tt class="docutils literal"><span class="pre">vote()</span></tt> est toujours requise. Néanmoins, elle doit être modifiée pour
  259. être utilisée dans les nouveaux templates et les nouvelles variables
  260. contextuelles.
  261. Changez l'appel au template <tt class="docutils literal"><span class="pre">polls/detail.html</span></tt> par <tt class="docutils literal"><span class="pre">polls/poll_detail.html</span></tt>,
  262. et passez <tt class="docutils literal"><span class="pre">object</span></tt> dans le contexte au lieu de <tt class="docutils literal"><span class="pre">poll</span></tt>.</p>
  263. <p>Lancez le serveur et utilisez votre nouvelle appli de sondage avec les vues
  264. génériques.</p>
  265. <p>Pour davantage de détails quant aux vues génériques, lisez la <a class="reference" href="http://www.djangoproject.com/documentation/generic_views/">documentation
  266. sur les vues génériques</a>.</p>
  267. <p></div>
  268. <div class="section">
  269. <h1><a id="venir" name="venir">À venir</a></h1>
  270. <p>Les tutoriels s'arrêtent ici pour le moment. Mais revenez prochainement pour la
  271. suite des réjouissances :</p>
  272. <blockquote>
  273. <ul class="simple">
  274. <li>Utilisation avancée des formulaires</li>
  275. <li>Utilisation du framework RSS</li></p>
  276. <li>Utilisation du framework de cache</li>
  277. <li>Utilisation du framework de commentaires</li>
  278. <li>Fonctionnalités avancées d'administration : Permissions</li>
  279. <li>Fonctionnalités avancées d'administration : Javascript</li>
  280. <p></ul>
  281. </blockquote>
  282. <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
  283. documentation de Django</a>.</p>
  284. <p>Cette traduction correspond à la révision 3589 (post 0.95).</p>
  285. </div></p>
  286. </div>
  287. </article>
  288. <footer>
  289. <h6 property="schema:datePublished">— 17/06/2006</h6>
  290. </footer>
  291. </section>
  292. <section>
  293. <div>
  294. <h3>Articles peut-être en rapport</h3>
  295. <ul>
  296. <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>
  297. <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>
  298. <li><a href="/david/biologeek/archives/20060617-redaction-de-votre-premiere-appli-django-partie-3-creation-des-vues-de-l-interface-publique/" title="Accès à Rédaction de votre première appli Django, partie 3 : Création des vues de l&#39;interface publique">Rédaction de votre première appli Django, partie 3 : Création des vues de l&#39;interface publique</a></li>
  299. </ul>
  300. </div>
  301. </section>
  302. <section>
  303. <div id="comments">
  304. <h3>Commentaires</h3>
  305. <div class="comment" typeof="schema:UserComments">
  306. <p class="comment-meta">
  307. <span class="comment-author" property="schema:creator">Play</span> le <span class="comment-date" property="schema:commentTime">24/06/2006</span> :
  308. </p>
  309. <div class="comment-content" property="schema:commentText">
  310. <p>David, je dis &quot;chapeau&quot; ! Excellents billets ! Continues comme ça ! C'est que du bon ! Django, c'est le bien :-)</p>
  311. </div>
  312. </div>
  313. <div class="comment" typeof="schema:UserComments">
  314. <p class="comment-meta">
  315. <span class="comment-author" property="schema:creator">Anthyme</span> le <span class="comment-date" property="schema:commentTime">18/07/2006</span> :
  316. </p>
  317. <div class="comment-content" property="schema:commentText">
  318. <p>Je te remerci beaucoup de tes tutoriels ... ils m'ont permis d'apprendre a une vitesse exteme les bases de Django.<br />
  319. Je suis impatient de voir la suite !<br />
  320. Encore un grand Merci !</p>
  321. </div>
  322. </div>
  323. <div class="comment" typeof="schema:UserComments">
  324. <p class="comment-meta">
  325. <span class="comment-author" property="schema:creator">David</span> le <span class="comment-date" property="schema:commentTime">19/07/2006</span> :
  326. </p>
  327. <div class="comment-content" property="schema:commentText">
  328. <p>J'attends les autres traductions avec impatience ! Good job !</p>
  329. </div>
  330. </div>
  331. <div class="comment" typeof="schema:UserComments">
  332. <p class="comment-meta">
  333. <span class="comment-author" property="schema:creator">David</span> le <span class="comment-date" property="schema:commentTime">06/09/2006</span> :
  334. </p>
  335. <div class="comment-content" property="schema:commentText">
  336. <p>Bonjour, si tu envisages une nouvelle traduction, je te propose la page sur les vues génériques, c'est vraiment pas simple à comprendre :-(<br />
  337. <a href="http://www.djangoproject.com/documentation/generic_views/" title="http://www.djangoproject.com/documentation/generic_views/" rel="nofollow">www.djangoproject.com/doc...</a><br />
  338. Sinon encore une fois très bon travail. Ton blog est la référence francophone sur Django !<br />
  339. <br />
  340. See U<br />
  341. David bis :)<br />
  342. <br />
  343. NB : à quand un tutoriel simple sur django ?<br />
  344. </p>
  345. </div>
  346. </div>
  347. <div class="comment" typeof="schema:UserComments">
  348. <p class="comment-meta">
  349. <span class="comment-author" property="schema:creator">David</span> le <span class="comment-date" property="schema:commentTime">06/09/2006</span> :
  350. </p>
  351. <div class="comment-content" property="schema:commentText">
  352. <p>En fait est-ce que Django peut générer un formulaire automatiquement ?<br />
  353. <br />
  354. Je m'explique je fais un petit site d'annonces. J'ai crée mon models.py pour générer ma bdd et l'auto admin du site. J'ai optimisé tout ça et l'admin du site est extra avec filtres et champ de recherche.<br />
  355. <br />
  356. Maintenant je dois faire le front-office, et je me demande comment faire la page de recherche et de résultats sans trop de galères avec les tempates, les vues et tout ce qui passe pas encore :-/<br />
  357. <br />
  358. David bis (en urgence rendu client)</p>
  359. </div>
  360. </div>
  361. <div class="comment" typeof="schema:UserComments">
  362. <p class="comment-meta">
  363. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">06/09/2006</span> :
  364. </p>
  365. <div class="comment-content" property="schema:commentText">
  366. <p>@David :<br />
  367. &gt; je te propose la page sur les vues génériques<br />
  368. <br />
  369. Ok, c'est noté ;-)<br />
  370. <br />
  371. &gt; NB : à quand un tutoriel simple sur django ?<br />
  372. <br />
  373. Ça arrive, j'ai ma petite idée là-dessus<br />
  374. <br />
  375. &gt; En fait est-ce que Django peut générer un formulaire automatiquement ?<br />
  376. <br />
  377. Oui, tu devrais jetter un œil à <a href="http://www.djangoproject.com/documentation/forms/" title="http://www.djangoproject.com/documentation/forms/" rel="nofollow">www.djangoproject.com/doc...</a></p>
  378. </div>
  379. </div>
  380. <div class="comment" typeof="schema:UserComments">
  381. <p class="comment-meta">
  382. <span class="comment-author" property="schema:creator">DJANGOJO</span> le <span class="comment-date" property="schema:commentTime">29/01/2007</span> :
  383. </p>
  384. <div class="comment-content" property="schema:commentText">
  385. <p>Bonjour,<br />
  386. <br />
  387. Voilà j'ai un petit souci et je n'arrive pas à le régler. Je suis vraiment novice avec django et on me demande de faire un petit site vite fait mais bien fait.<br />
  388. <br />
  389. En faite j'ai un MENU qui se compléte avec un sous menu. J'aimerai que quand je clique sur un menu, le sous menu s'affiche juste en dessous.<br />
  390. J'ai mis une clé primaire entre les sous menu et le menu donc j'arrive à afficher le sous menu en fonction du menu. <br />
  391. <br />
  392. Le seul problème c'est d'afficher dans la même page le sous menu.<br />
  393. <br />
  394. j'aimerai de l'aide svp. <br />
  395. MERCI. </p>
  396. </div>
  397. </div>
  398. <div class="comment" typeof="schema:UserComments">
  399. <p class="comment-meta">
  400. <span class="comment-author" property="schema:creator">Anthony</span> le <span class="comment-date" property="schema:commentTime">05/03/2007</span> :
  401. </p>
  402. <div class="comment-content" property="schema:commentText">
  403. <p>Bonjour !<br />
  404. <br />
  405. Originaire du monde Java (les méchants), je dois avouer être impressionné par la performance de ce framework.<br />
  406. Un grand bravo également pour ces billets sans lesquels je ne serais certainement jamais intéressé à Django.<br />
  407. <br />
  408. J'ai une question simple :<br />
  409. &quot; vote{{ choice.votes|pluralize }} &quot;<br />
  410. Renvoie :<br />
  411. - &quot;vote&quot; pour 1 vote<br />
  412. - &quot;votes&quot; pour 2 votes et plus<br />
  413. - mais &quot;votes&quot; pour 0 vote<br />
  414. A quoi ce problème est-il dû et peut-on le contourner sans avoir à utiliser de conditions ? (je trouvais cette fonction intéressante, mais si elle ne marche pas, à quoi bon ? :) )<br />
  415. <br />
  416. Merci d'avance et encore bravo.<br />
  417. Anthony.</p>
  418. </div>
  419. </div>
  420. <div class="comment" typeof="schema:UserComments">
  421. <p class="comment-meta">
  422. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">05/03/2007</span> :
  423. </p>
  424. <div class="comment-content" property="schema:commentText">
  425. <p>Salut Anthony, et bienvenue dans le monde de Django :-)<br />
  426. <br />
  427. Le mieux est d'entourer ta réponse d'un if choices.votes pour écrire une phrase adaptée du style &quot;il n'y a pas de votes&quot; qui est plus joli qu'un &quot;il y a 0 votes&quot;. D'ailleurs maintenant que je l'écris, il me semble qu'il est grammaticalement correct de mettre un &quot;s&quot; lorsque la quantité est nulle, comme dans la première phrase.</p>
  428. </div>
  429. </div>
  430. <div class="comment" typeof="schema:UserComments">
  431. <p class="comment-meta">
  432. <span class="comment-author" property="schema:creator">Anthony</span> le <span class="comment-date" property="schema:commentTime">06/03/2007</span> :
  433. </p>
  434. <div class="comment-content" property="schema:commentText">
  435. <p>Très correct, j'avais seulement trouvé cela étrange en jouant avec le tutorial.<br />
  436. En regardant rapidement les bug reports de Django, j'ai trouvé que les anglo-saxons avaient demandé exactement l'inverse.<br />
  437. La fonction renvoyait &quot;0 vote&quot; à l'origine, puis ils l'ont changée pour afficher &quot;0 votes&quot;, ce qui est effectivement valide, mais en anglais ^^<br />
  438. Rendez-nous Jeanne d'Arc...<br />
  439. <br />
  440. Merci pour ta réponse rapide et désolé pour ma question ;)<br />
  441. Anthony.</p>
  442. </div>
  443. </div>
  444. <div class="comment" typeof="schema:UserComments">
  445. <p class="comment-meta">
  446. <span class="comment-author" property="schema:creator">JoJO</span> le <span class="comment-date" property="schema:commentTime">30/03/2007</span> :
  447. </p>
  448. <div class="comment-content" property="schema:commentText">
  449. <p>Bonjour à tous !!!<br />
  450. <br />
  451. Voilà, j'ai vu qu'il y a pas mal de chose à faire du coté administration django, mais est-il possible d'avoir, pour un champ &quot;TextField&quot; une zone de texte avec possibilité de le mettre en forme, avec couleur, police , insérer une icône ... ? En breffff comme on peut le voir dans certain forum ou genre MSN !!!<br />
  452. Pour avoir un site complétement dynamique, de pouvoir mettre le texte totalement en forme dans la partie administration !!<br />
  453. <br />
  454. Merci bien !<br />
  455. Jo</p>
  456. </div>
  457. </div>
  458. <div class="comment" typeof="schema:UserComments">
  459. <p class="comment-meta">
  460. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">30/03/2007</span> :
  461. </p>
  462. <div class="comment-content" property="schema:commentText">
  463. <p>@JoJO : tu devrais jeter un œil à <a href="http://code.djangoproject.com/wiki/RichTextField" title="http://code.djangoproject.com/wiki/RichTextField" rel="nofollow">code.djangoproject.com/wi...</a> ou si tu utilises les newforms à <a href="http://code.djangoproject.com/wiki/CustomWidgetsTinyMCE" title="http://code.djangoproject.com/wiki/CustomWidgetsTinyMCE" rel="nofollow">code.djangoproject.com/wi...</a><br />
  464. <br />
  465. Bonne continuation :-).</p>
  466. </div>
  467. </div>
  468. <div class="comment" typeof="schema:UserComments">
  469. <p class="comment-meta">
  470. <span class="comment-author" property="schema:creator">Warflo</span> le <span class="comment-date" property="schema:commentTime">20/05/2007</span> :
  471. </p>
  472. <div class="comment-content" property="schema:commentText">
  473. <p>Je me demande quand même quelque chose:<br />
  474. Django respecte le MVC ?<br />
  475. Le traitement des donnés avant d'être affichés sont sensé être fait par le Modèle.<br />
  476. Or dans Django, c'est dans la Vue que l'on traite les donnés avant de les passer au moteur de template, donc avant de définir leur mise en forme, alors que si l'on respecte le MVC, c'est dans le Modèle que les donnés sont traité.<br />
  477. Mon raisonement est-il bon ?<br />
  478. <br />
  479. </p>
  480. </div>
  481. </div>
  482. <div class="comment" typeof="schema:UserComments">
  483. <p class="comment-meta">
  484. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">20/05/2007</span> :
  485. </p>
  486. <div class="comment-content" property="schema:commentText">
  487. <p>Je ne suis pas un spécialiste du modèle MVC mais il faut déjà savoir que c'est MTV pour django donc les correspondances entre les noms ne sont pas vraiment les mêmes (cf. <a href="http://www2.jeffcroft.com/blog/2007/jan/11/django-and-mtv/" title="http://www2.jeffcroft.com/blog/2007/jan/11/django-and-mtv/" rel="nofollow">www2.jeffcroft.com/blog/2...</a> ).<br />
  488. <br />
  489. Concernant maintenant le traitement dans les Vues et non dans les Modèles, c'est vrai que cela ne respecte pas le MVC strict mais c'est ce qui est communément fait dans les frameworks web car le modèle joue généralement le rôle d'ORM avec la base de données (c'est d'ailleurs peut-être ce que l'on pourrait appeler traitement ce rapatriement des données). Après il faut savoir aussi que les Managers (dans les Modèles) peuvent être utilisés pour traiter en quelque sorte les données.<br />
  490. <br />
  491. On peut d'ailleurs lire sur wikipédia ( <a href="http://fr.wikipedia.org/wiki/MVC" title="http://fr.wikipedia.org/wiki/MVC" rel="nofollow">fr.wikipedia.org/wiki/MVC</a> ) : « Le MVC montre ses limites dans le cadre des applications utilisant les technologies du web, bâties à partir de serveurs d'applications. »<br />
  492. <br />
  493. Donc en conclusion le raisonnement est bon mais le fait que ce soit un framework web change un peu la donne.</p>
  494. </div>
  495. </div>
  496. <div class="comment" typeof="schema:UserComments">
  497. <p class="comment-meta">
  498. <span class="comment-author" property="schema:creator">Warflo</span> le <span class="comment-date" property="schema:commentTime">21/05/2007</span> :
  499. </p>
  500. <div class="comment-content" property="schema:commentText">
  501. <p>Ok, merci des précisions ;)</p>
  502. </div>
  503. </div>
  504. </div>
  505. </section>
  506. <footer>
  507. <nav>
  508. <p>
  509. <small>
  510. Je réponds quasiment toujours aux <a href="m&#x61;ilto:d&#x61;vid%40l&#x61;rlet&#46;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>
  511. </small>
  512. </p>
  513. </nav>
  514. </footer>
  515. </div>
  516. <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
  517. <script data-no-instant>InstantClick.init()</script>
  518. </body>
  519. </html>