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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <!doctype html>
  2. <html lang=fr>
  3. <head>
  4. <!-- Always define the charset before the title -->
  5. <meta charset=utf-8>
  6. <title>Son propre TinyURL en Python et HTML5 avec webpy — 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/20090221-son-propre-tinyurl-en-python-et-html5-avec-webpy">
  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">Son propre TinyURL en Python et HTML5 avec webpy</h1>
  42. <article typeof="schema:BlogPosting">
  43. <div property="schema:articleBody">
  44. <img src="/static/david/biologeek/images/logos/bitly.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
  45. <p>Avec Twitter, la concision est de mise. Tout le monde utilise des "raccourcisseurs" d'URL comme TinyURL ou Bit.ly mais ça pose plusieurs problèmes : vous n'avez aucune idée de la pérennité du service (et en ce moment on voit bien le problème des services gratuits et non rentables qui ferment) et aucune garantie que les liens seront toujours redirigés vers les bonnes destinations sans passer par une pub/un outil de traçabilité/insérez votre délire parano ici.</p>
  46. <p>J'ai enregistré hier bgk.me pour remédier à ça et avoir mon propre service de redirections courtes. Ça prend une centaine de lignes en Python et c'est sous <a href="http://sam.zoy.org/wtfpl/">WTFPL</a>, comme ce blog. Enfin HTML5 c'est juste pour être plus concis, rien de bien évolué dans ce domaine, allez voir l'<a href="http://svay.com/blog/index/post/2009/02/19/Creer-un-client-Twitter-offline-pour-l-iPhone-avec-HTML5">excellent billet de Maurice</a> si vous voulez apprendre à exploiter certaines capacités utiles de HTML5.</p>
  47. <h2>Choix techniques</h2>
  48. <p>Au niveau des fonctionnalités :</p>
  49. <ul>
  50. <li>la possibilité de rediriger facilement vers mes billets ou mes brèves ;</li>
  51. <li>la possibilité de choisir un nom de raccourci pertinent (je déteste les tinyurls qui ont un hash ne permettant pas d'avoir une idée de ce qu'il y a derrière) ;</li>
  52. <li>une interface d'administration simpliste.</li>
  53. </ul>
  54. <p>Il y a des centaines de façons de coder ça et j'aurais aussi pu utiliser <a href="http://ur1.ca/">ur1</a> en PHP <a href="http://twitter.com/znarf/status/1230052100">mentionné par znarf</a>, je pense que c'est une bonne solution aussi, tout dépend de votre infrastructure. <strong>Edit</strong> : <a href="http://twitter.com/xavierlacot/status/1232570280">Xavier vient de mentionner urly</a> en Python aussi.</p>
  55. <p>Je voulais rester super simple, un seul fichier, pas de base de données et une base qui ne soit pas une usine à gaz comme Django, inutile dans notre cas. J'ai donc opté pour <a href="http://webpy.org/">webpy</a> qui est excellent pour ça, bon c'est devenu un peu trop complet à mon goût encore (ah le bon temps où ça tenait dans un fichier unique :-)) mais suffisamment simple à prendre en main pour ceux qui voudraient se mettre à Python ;-).</p>
  56. <h2>Redirections</h2>
  57. <p>On commence par les redirections des billets et brèves, il faut pour cela ajouter les URL suivantes :</p>
  58. <pre><code>urls = (
  59. "/p/(\d+)", "RedirectToPost",
  60. "/t/(\d+)", "RedirectToThought",
  61. )
  62. </code></pre>
  63. <p>Et ensuite construire les classes de redirection :</p>
  64. <pre><code>class RedirectToPost:
  65. def GET(self, post_id):
  66. return web.redirect(POST_REDIRECT_URL % post_id)
  67. class RedirectToThought:
  68. def GET(self, thought_id):
  69. return web.redirect(THOUGHT_REDIRECT_URL % thought_id)
  70. </code></pre>
  71. <p>Ici vous pouvez voir que j'ai misé sur la réutilisation du code en définissant pas mal de variables en début de fichier permettant d'adapter facilement le code à votre propre usage. Grâce à ces redirections, <a href="http://bgk.me/p/270">http://bgk.me/p/270</a> va rediriger vers ce billet par exemple.</p>
  72. <p>Passons maintenant au redirections vers d'autres URL, ici aussi il faut ajouter une entrée dans les URL :</p>
  73. <pre><code>urls = (
  74. "/(.*)", "RedirectToOthers",
  75. )
  76. </code></pre>
  77. <p>Là il faut aller chercher les URL qui ont été créées via l'admin (que l'on verra ensuite) et qui sont stockées dans un objet shelve qui permet rapidement d'avoir une correspondance clé-valeur en Python.</p>
  78. <pre><code>class RedirectToOthers:
  79. def GET(self, short_name):
  80. storage = shelve.open(SHELVE_FILENAME)
  81. # shelve does not allow unicode keys
  82. short_name = str(short_name)
  83. if storage.has_key(short_name):
  84. response = web.redirect(storage[short_name])
  85. else:
  86. response = FAIL_MESSAGE
  87. storage.close()
  88. return response
  89. </code></pre>
  90. <p>Ici aussi ça reste très simple puisque ça redirige vers l'URL trouvée ou ça affiche un message d'erreur.</p>
  91. <h2>Administration</h2>
  92. <p>Bon si vous avez toujours un shell ouvert sur votre serveur, vous pouvez directement remplir votre fichier shelve avec le shell Python. Mais ça coûte pas grand chose de faire une admin toute simple pour pouvoir faire ça en web alors on ne va pas s'en priver.</p>
  93. <p>Pour protéger cette URL, on va juste la rendre difficile à trouver, je vous laisser utiliser ce qui vous semble le plus pertinent, ici aussi dans une variable :</p>
  94. <pre><code>urls = (
  95. ADMIN, "Admin",
  96. ADMIN+"/done/(.*)", "AdminDone",
  97. )
  98. </code></pre>
  99. <p>La classe Admin vous permet d'afficher le formulaire et de soumettre une nouvelle correspondance raccourci-url :</p>
  100. <pre><code>class Admin:
  101. def GET(self):
  102. admin_form = web.form.Form(
  103. web.form.Textbox("url", description="Long URL"),
  104. web.form.Textbox("shortcut",description="Shortcut"),
  105. )
  106. admin_template = web.template.Template("""$def with(form)
  107. &lt;!DOCTYPE HTML&gt;
  108. &lt;html lang="en"&gt;
  109. &lt;head&gt;
  110. &lt;meta charset=utf-8&gt;
  111. &lt;title&gt;URL shortener administration&lt;/title&gt;
  112. &lt;/head&gt;
  113. &lt;body onload="document.getElementById('url').focus()"&gt;
  114. &lt;header&gt;&lt;h1&gt;Admin&lt;/h1&gt;&lt;/header&gt;
  115. &lt;form method="POST" action="/admin"&gt;
  116. $:form.render()
  117. &lt;input type="submit" value="Shorten this long URL"&gt;
  118. &lt;/form&gt;
  119. &lt;/body&gt;
  120. &lt;/html&gt;
  121. """)
  122. return admin_template(admin_form())
  123. def POST(self):
  124. data = web.input()
  125. shortcut = str(data.shortcut) or random_shortcut()
  126. storage = shelve.open(SHELVE_FILENAME)
  127. if storage.has_key(shortcut) or not data.url:
  128. response = web.badrequest()
  129. else:
  130. storage[shortcut] = data.url
  131. response = web.seeother(ADMIN+'/done/'+shortcut)
  132. storage.close()
  133. return response
  134. </code></pre>
  135. <p>Les formulaires et templates de webpy sont utilisés directement dans le code ici car ils restent super concis. Si c'est un GET on construit le formulaire et on l'envoie au template, si c'est un POST on ajoute l'URL à la base et on redirige vers la page de confirmation. Très peu de vérifications car ça ne sert pas à grand chose dans ce cas, on s'assure juste de ne pas écraser une URL existante et qu'une URL a bien été soumise.</p>
  136. <p>Il ne reste plus qu'à afficher une page la page de confirmation avec le lien nouvellement créer (en dur sinon on pourrait facilement détecter votre admin grâce au referer...) et un raccourci pour tweeter le lien directement :</p>
  137. <pre><code>class AdminDone:
  138. def GET(self, short_name):
  139. admin_done_template = web.template.Template("""$def with(new_url)
  140. &lt;!DOCTYPE HTML&gt;
  141. &lt;html lang="en"&gt;
  142. &lt;head&gt;
  143. &lt;meta charset=utf-8&gt;
  144. &lt;title&gt;URL shortener administration&lt;/title&gt;
  145. &lt;/head&gt;
  146. &lt;body&gt;
  147. &lt;header&gt;&lt;h1&gt;Done!&lt;/h1&gt;&lt;/header&gt;
  148. &lt;p&gt;You created: $new_url&lt;/p&gt;
  149. &lt;p&gt;&lt;a href="http://twitter.com/home?status=$new_url"
  150. title="Tweet it!"&gt;Tweet it?&lt;/a&gt;&lt;/p&gt;
  151. &lt;/body&gt;
  152. &lt;/html&gt;
  153. """)
  154. return admin_done_template(SERVICE_URL+short_name)
  155. </code></pre>
  156. <p>Et voilà, après vous pouvez ajouter tout pleins de choses mais la base est là, suffisante pour mon usage. Ça m'a pris 2h et 10€ (car ils se gavent sur les .me mais c'est la seule extension qu'il restait) mais c'est le prix de l'indépendance.</p>
  157. <h2>Mise en production</h2>
  158. <p>J'utilise <a href="http://www.lighttpd.net/">lighty</a>, à adapter selon votre configuration (ne pas oublier de rendre code.py exécutable et de modifier ADMIN !) :</p>
  159. <pre><code>$HTTP["host"] =~ "bgk.me" {
  160. server.document-root = "/path/"
  161. fastcgi.server = (
  162. "/code.py" =&gt; (
  163. "main" =&gt; (
  164. "socket" =&gt; "/path/bgkme.socket",
  165. "bin-path" =&gt; "/path/code.py",
  166. "max-procs" =&gt; 1,
  167. "bin-environment" =&gt; (
  168. "REAL_SCRIPT_NAME" =&gt; ""
  169. ),
  170. "check-local" =&gt; "disable"
  171. )
  172. )
  173. )
  174. url.rewrite-once = (
  175. "^(/.*)$" =&gt; "/code.py$1",
  176. )
  177. }
  178. </code></pre>
  179. <p>Pour terminer, <a href="http://code.welldev.org/bgk/">le code est sur ma ferme de dépôts</a>, à utiliser, modifier, critiquer sans modération, enjoy!</p>
  180. </div>
  181. </article>
  182. <footer>
  183. <h6 property="schema:datePublished">— 21/02/2009</h6>
  184. </footer>
  185. </section>
  186. <section>
  187. <div>
  188. <h3>Articles peut-être en rapport</h3>
  189. <ul>
  190. <li><a href="/david/biologeek/archives/20090125-mieux-communiquer-sur-openid-et-oauth/" title="Accès à Mieux communiquer sur OpenID et OAuth">Mieux communiquer sur OpenID et OAuth</a></li>
  191. <li><a href="/david/biologeek/archives/20080902-sortie-de-django-10-une-annee-de-nouveautes/" title="Accès à Sortie de Django 1.0, une année de nouveautés">Sortie de Django 1.0, une année de nouveautés</a></li>
  192. <li><a href="/david/biologeek/archives/20080723-ipheedsorg-une-version-iphone-pour-votre-blog/" title="Accès à ★ iPheeds.org, une version iPhone pour votre blog">★ iPheeds.org, une version iPhone pour votre blog</a></li>
  193. </ul>
  194. </div>
  195. </section>
  196. <section>
  197. <div id="comments">
  198. <h3>Commentaires</h3>
  199. <div class="comment" typeof="schema:UserComments">
  200. <p class="comment-meta">
  201. <span class="comment-author" property="schema:creator">Yoan</span> le <span class="comment-date" property="schema:commentTime">21/02/2009</span> :
  202. </p>
  203. <div class="comment-content" property="schema:commentText">
  204. <p>Oho, même toi tu es diabolique : body onload=&quot;document.getElementById(&#39;url&#39;).focus()&quot;</p>
  205. <p>Sinon, juste pour dire qu&#39;HTML 5 est un peu plus qu&#39;un doctype dont il est possible de se souvenir. Tu peux supprimer les balises head et body de ta page et utilise cette splendide balise meta: &lt;meta charset=utf-8&gt; et n&#39;oublie pas l&#39;attribut lang sur ta balise html, ça fait toujours plaisir. Et as-tu jeter un œil à autofocus? C&#39;est toujours aussi diabolique à mon sens, mais il est possible que le navigateur gère ça de manière plus agréable.</p>
  206. <p>Sinon, je découvre les web.form.Form et ai déjà des frissons dans le dos.</p>
  207. </div>
  208. </div>
  209. <div class="comment" typeof="schema:UserComments">
  210. <p class="comment-meta">
  211. <span class="comment-author" property="schema:creator">Damien B</span> le <span class="comment-date" property="schema:commentTime">21/02/2009</span> :
  212. </p>
  213. <div class="comment-content" property="schema:commentText">
  214. <p>&quot;Enfin HTML5 c&#39;est juste pour être plus concis&quot;</p>
  215. <p>Tu veux dire, HTML 5 peut-être ?</p>
  216. <p>&quot;&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; UTF-8&quot; /&gt;&quot;</p>
  217. <p>validator.nu dit : &quot;Error: Bad value text/html; UTF-8 for attribute content on element meta: The legacy encoding did not contain charset= immediately after the space.</p>
  218. <p>From line 4, column 13; to line 4, column 73&quot;</p>
  219. <p>Ralalalala : trop concis.</p>
  220. <p>&quot;&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; UTF-8&quot; /&gt;&quot;</p>
  221. <p>§8.1.2.1 point 6 dit très clairement que /&gt; est tout à fait optionnel, tu aurais donc pu finir par &#39;UTF-8&quot;&gt;&#39; : deux caractères de gagnés pour la concision. Et pareil pour les input.</p>
  222. <p>&quot;&lt;header&gt;&lt;h1&gt;Admin&lt;/h1&gt;&lt;/header&gt;&quot;</p>
  223. <p>Vu la taille et le contenu du document, header est totalement inutile : 17 caractères de gagnés.</p>
  224. <p>Au final, avec tout ce qu&#39;on gagne, tu peux te permettre de mettre<br />&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;&gt;<br />sans perdre un caractère de concision, et tu es valide par rapport aux spécifications publiées :) Bon, c&#39;est vrai qu&#39;au passage on perd un effet de manche : c&#39;est dommage :-P</p>
  225. </div>
  226. </div>
  227. <div class="comment" typeof="schema:UserComments">
  228. <p class="comment-meta">
  229. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  230. </p>
  231. <div class="comment-content" property="schema:commentText">
  232. <p>Ok, bon je vais être honnête j&#39;ai fait un vilain copier-coller de l&#39;en-tête de l&#39;ami mauriz et j&#39;aurais pas dû, surtout que j&#39;ai été assez faignant pour pas valider le code ensuite... bref, mea culpa, je vais corriger ça.</p>
  233. <p>@Yoan : par contre autofocus, tu as un lien pour ça ?</p>
  234. </div>
  235. </div>
  236. <div class="comment" typeof="schema:UserComments">
  237. <p class="comment-meta">
  238. <span class="comment-author" property="schema:creator">Damien B</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  239. </p>
  240. <div class="comment-content" property="schema:commentText">
  241. <p>Tiens, pour autofocus : <a href="http://dev.w3.org/html5/spec/Overview.html#autofocusing-a-form-control">http://dev.w3.org/html5/spec/Overview.html#autofocusing-a-form-control</a></p>
  242. <p>Et tu feras attention sur ton blog, ton colorisateur syntaxique n&#39;est pas assez pragmatique pour détecter &quot;header&quot;. Mwahahaha.</p>
  243. </div>
  244. </div>
  245. <div class="comment" typeof="schema:UserComments">
  246. <p class="comment-meta">
  247. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  248. </p>
  249. <div class="comment-content" property="schema:commentText">
  250. <p>Merci Damien, bon du coup je vais plus pouvoir utiliser les forms de webpy, ce qui ne va pas non plus trop me manquer.</p>
  251. <p>Et sinon oui, je viens de mettre à jour le highlight.js :p</p>
  252. </div>
  253. </div>
  254. <div class="comment" typeof="schema:UserComments">
  255. <p class="comment-meta">
  256. <span class="comment-author" property="schema:creator">Damien B</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  257. </p>
  258. <div class="comment-content" property="schema:commentText">
  259. <p>Sinon, pas terrible d&#39;avoir fait sauter le titre du post du fil de commentaires, on ne sait plus à quelle conversation ça appartient.</p>
  260. </div>
  261. </div>
  262. <div class="comment" typeof="schema:UserComments">
  263. <p class="comment-meta">
  264. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  265. </p>
  266. <div class="comment-content" property="schema:commentText">
  267. <p>Bien vu, et corrigé. C&#39;est dû à ma récente utilisation de la solution native de Django pour les commentaires. Merci pour le report de bug :)</p>
  268. </div>
  269. </div>
  270. <div class="comment" typeof="schema:UserComments">
  271. <p class="comment-meta">
  272. <span class="comment-author" property="schema:creator">Yoan</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  273. </p>
  274. <div class="comment-content" property="schema:commentText">
  275. <p>L&#39;ami Lachlan (<a href="http://standardssuck.org/">http://standardssuck.org/</a>) a écrit une série de tests concernant l&#39;autofocus : <a href="http://lachy.id.au/dev/markup/tests/html5/autofocus/">http://lachy.id.au/dev/markup/tests/html5/autofocus/</a></p>
  276. <p>Oui, le premier doctest des forms web.py donne des boutons. Web.py contient trop d&#39;outils dont on a pas envie de se servir à mon goût.</p>
  277. <p>&gt;&gt;&gt; import web<br />&gt;&gt;&gt; web.utils.commify(1234567890)<br />&#39;1,234,567,890&#39;<br />&gt;&gt;&gt; web.utils.nthstr(1001)<br />&#39;1001st&#39;</p>
  278. <p>Certaines choses doivent rester hors d&#39;un web framework dont le motto est d&#39;être simple et puissant. Je trouve Werkzeug séduisant, même si je passe pas mal de temps à jouer avec Restish. Enfin, bref, les goûts et les couleurs comme on dit.</p>
  279. </div>
  280. </div>
  281. <div class="comment" typeof="schema:UserComments">
  282. <p class="comment-meta">
  283. <span class="comment-author" property="schema:creator">sebsauvage</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  284. </p>
  285. <div class="comment-content" property="schema:commentText">
  286. <p>web.py est pas mal, oui.<br />Mais comme toi, parfois je cherche encore plus minimal. J&#39;ai fini par écrire le mien (pour ce que ça vaut):</p>
  287. <p><a href="http://sebsauvage.net/python/snyppets/#simplewebdispatcher">http://sebsauvage.net/python/snyppets/#simplewebdispatcher</a></p>
  288. <p>Amusant à faire, et vraiment minimaliste.</p>
  289. <p>Un petit coup de l&#39;excellent SQLite là dessus et des cookies , et on a ce qu&#39;il faut pour gérer les sessions.</p>
  290. </div>
  291. </div>
  292. <div class="comment" typeof="schema:UserComments">
  293. <p class="comment-meta">
  294. <span class="comment-author" property="schema:creator">NiCoS</span> le <span class="comment-date" property="schema:commentTime">22/02/2009</span> :
  295. </p>
  296. <div class="comment-content" property="schema:commentText">
  297. <p>Si tu devais faire un petit comparatif web.py / django, tu en dirais quoi ?</p>
  298. <p>J&#39;avias vu web.py il y a qqs temps mais pour éviter de me disperser, je l&#39;avais laissé de coté. Vous avez déjà tous l&#39;air de lui reprocher le fait qu&#39;il ne soit plus aussi léger qu&#39;auparavant...</p>
  299. </div>
  300. </div>
  301. <div class="comment" typeof="schema:UserComments">
  302. <p class="comment-meta">
  303. <span class="comment-author" property="schema:creator">Pierre-Jean</span> le <span class="comment-date" property="schema:commentTime">23/02/2009</span> :
  304. </p>
  305. <div class="comment-content" property="schema:commentText">
  306. <p>&gt; NiCoS, A l&#39;époque où je l&#39;avais regardé, le code source de web.py comportait beaucoup de &quot;magic&quot;.</p>
  307. <p>Mais suite à cet article je vais refaire un petit tour d&#39;évaluation.</p>
  308. </div>
  309. </div>
  310. <div class="comment" typeof="schema:UserComments">
  311. <p class="comment-meta">
  312. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">23/02/2009</span> :
  313. </p>
  314. <div class="comment-content" property="schema:commentText">
  315. <p>@Yoan : merci pour les liens, bon la conclusion c&#39;est que ça ne fonctionne pas encore dans mes versions de Firefox ou Safari...</p>
  316. <p>C&#39;est marrant car j&#39;ai failli le faire avec werkzeug, je vais jeter un œil à restish.</p>
  317. <p>@sebsauvage : au bout d&#39;un moment c&#39;est fatigant (mais intéressant...) de tout refaire à la main ;-)</p>
  318. <p>@NiCoS :</p>
  319. <p>&gt; Si tu devais faire un petit comparatif web.py / django, tu en dirais quoi ?</p>
  320. <p>Pas les mêmes usages/objectifs, tout dépend des besoins du projet, comme toujours.</p>
  321. <p>@Pierre-Jean : au plus tu simplifies et au plus ça devient magique, forcément (à moins de créer un langage qui soit vraiment orienté web ?), le tout est de trouver le bon équilibre !</p>
  322. </div>
  323. </div>
  324. <div class="comment" typeof="schema:UserComments">
  325. <p class="comment-meta">
  326. <span class="comment-author" property="schema:creator">NiCoS</span> le <span class="comment-date" property="schema:commentTime">23/02/2009</span> :
  327. </p>
  328. <div class="comment-content" property="schema:commentText">
  329. <p>En fait, oups, j&#39;ai confusionné avec web2py (<a href="http://mdp.cti.depaul.edu/">http://mdp.cti.depaul.edu/</a>) qui semble plus proche de django que web.py ;-)</p>
  330. <p>Après lecture du site, en effet, rien à voir !</p>
  331. </div>
  332. </div>
  333. <div class="comment" typeof="schema:UserComments">
  334. <p class="comment-meta">
  335. <span class="comment-author" property="schema:creator">desfrenes</span> le <span class="comment-date" property="schema:commentTime">10/03/2009</span> :
  336. </p>
  337. <div class="comment-content" property="schema:commentText">
  338. <p>je crois aussi qu&#39;une comparaison djang/web2py un minimum objective (cad pas faite par l&#39;auteur de web2py!) serait intéressante.</p>
  339. </div>
  340. </div>
  341. <div class="comment" typeof="schema:UserComments">
  342. <p class="comment-meta">
  343. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">12/03/2009</span> :
  344. </p>
  345. <div class="comment-content" property="schema:commentText">
  346. <p>Les comparaisons/benchmarks objectifs sont assez rares :)</p>
  347. </div>
  348. </div>
  349. <div class="comment" typeof="schema:UserComments">
  350. <p class="comment-meta">
  351. <span class="comment-author" property="schema:creator">desfrenes</span> le <span class="comment-date" property="schema:commentTime">15/03/2009</span> :
  352. </p>
  353. <div class="comment-content" property="schema:commentText">
  354. <p>Y compris ton article dans linux mag? ;-)</p>
  355. </div>
  356. </div>
  357. <div class="comment" typeof="schema:UserComments">
  358. <p class="comment-meta">
  359. <span class="comment-author" property="schema:creator">David, biologeek</span> le <span class="comment-date" property="schema:commentTime">16/03/2009</span> :
  360. </p>
  361. <div class="comment-content" property="schema:commentText">
  362. <p>Héhé, surtout celui-là ! :-)</p>
  363. </div>
  364. </div>
  365. <div class="comment" typeof="schema:UserComments">
  366. <p class="comment-meta">
  367. <span class="comment-author" property="schema:creator">neofutur</span> le <span class="comment-date" property="schema:commentTime">19/08/2011</span> :
  368. </p>
  369. <div class="comment-content" property="schema:commentText">
  370. <p>dns le genre alternatives en php, voir aussi casimir :</p>
  371. <p><a href="https://github.com/nhoizey/casimir">https://github.com/nhoizey/casimir</a></p>
  372. <p>et mon fork avec 1 ou 2 features en plus, et quelques fixes pour le php 5.3 :<br /><a href="https://github.com/neofutur/casimir">https://github.com/neofutur/casimir</a></p>
  373. </div>
  374. </div>
  375. </div>
  376. </section>
  377. <footer>
  378. <nav>
  379. <p>
  380. <small>
  381. 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>
  382. </small>
  383. </p>
  384. </nav>
  385. </footer>
  386. </div>
  387. <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
  388. <script data-no-instant>InstantClick.init()</script>
  389. </body>
  390. </html>