<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le Mad Blog &#187; Développement</title>
	<atom:link href="http://j-mad.com/blog/category/developpement/feed/" rel="self" type="application/rss+xml" />
	<link>http://j-mad.com/blog</link>
	<description>juste un blog</description>
	<lastBuildDate>Sun, 11 Jul 2010 20:34:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Django-improved-inlines, enrichissez facilement vos contenus et ça, sans payer l&#8217;ISF</title>
		<link>http://j-mad.com/blog/2010/06/20/django-improved-inlines-enrichissez-facilement-vos-contenus-et-ca-sans-payer-lisf/</link>
		<comments>http://j-mad.com/blog/2010/06/20/django-improved-inlines-enrichissez-facilement-vos-contenus-et-ca-sans-payer-lisf/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 14:15:26 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[La Django-app du mois]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=675</guid>
		<description><![CDATA[
			
				
			
		
La pluie ayant décidé d&#8217;être l&#8217;invité surprise du week-end, j&#8217;ai donc une bonne excuse pour ne pas aller prendre des coups de soleil à la plage mais rester bien tranquillement sur mon clavier. Autant donc en profiter pour vous parler de l&#8217;application django du mois, j&#8217;ai nommé django-improved-inlines. Oui, je sais, elle a un nom [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F06%2F20%2Fdjango-improved-inlines-enrichissez-facilement-vos-contenus-et-ca-sans-payer-lisf%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F06%2F20%2Fdjango-improved-inlines-enrichissez-facilement-vos-contenus-et-ca-sans-payer-lisf%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>La pluie ayant décidé d&#8217;être l&#8217;invité surprise du week-end, j&#8217;ai donc une bonne excuse pour ne pas aller prendre des coups de soleil à la plage mais rester bien tranquillement sur mon clavier. Autant donc en profiter pour vous parler de l&#8217;application django du mois, j&#8217;ai nommé django-improved-inlines. Oui, je sais, elle a un nom à rallonge. Django-improved-inlines est en fait une version légèrement dopé de django-inlines (d&#8217;où le improved) qui fait elle même parti du package <a href="http://github.com/nathanborror/django-basic-apps">django-basic-apps</a>. Oui je sais, ça commence à faire un arbre généalogique digne d&#8217;une série américaine (ou du trône de fer).</p>
<h1>1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?</h1>
<p>Vous le trouverez sur sa page <a href="http://github.com/issackelly/django-improved-inlines">github</a>. C&#8217;est d&#8217;ailleurs là que vous pourrez apprendre que cette sympathique petite app est une version modifiée de l&#8217;app inlines de django-basic-apps.</p>
<p>Pour l&#8217;installation deux méthodes :<br />
directement en clonant le repository git de github<br />
avec un petit easy_install bien de chez nous.</p>
<p>Attention, l&#8217;application pour fonctionner à besoin de <a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a> mais l&#8217;installation par easy_install ne vous l&#8217;installera pas automatiquement. Un petit easy_install beautifulsoup sera donc de rigueur. Et oui.</p>
<p>Quand à la doc, elle tient dans un mouchoir de poche, à savoir le fichier readme mais au vu de la simplicité de l&#8217;app, ce n&#8217;est pas vraiment dérangeant.</p>
<h1>2- Mais au fait, à quoi ça sert ?</h1>
<p>En fait c&#8217;est tout simple. Cela vous permet, lorsque vous rédigez des contenus, d&#8217;insérer à l&#8217;intérieur d&#8217;autre contenu gérer par votre django. Et en les mettant en forme avec des templates spécifiques.</p>
<p>Imaginons par exemple que vous voulez insérez des images d&#8217;une manière simple dans un billet de blog, ou des blocks de texte ou ce que vous voulez en fait. Et cela, sans modifier le template de votre contenu principal. Et oui. Mais non, ce n&#8217;est pas de la magie.</p>
<h1>3- Comment ça marche ?</h1>
<p>En fait, cela marche en deux temps. Tout d&#8217;abord dans le template d&#8217;affichage de votre contenu principal, il faut déclarer et utiliser le template de django-improved-inlines, comme ceci :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: black;">&#123;</span><span style="color: #66cc66;">%</span> load inlines <span style="color: #66cc66;">%</span><span style="color: black;">&#125;</span><br />
…....<br />
<span style="color: black;">&#123;</span><span style="color: black;">&#123;</span> post.<span style="color: black;">body</span>|render_inlines <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span></div></div>
<p>Ensuite, tout va se jouer dans votre contenu, ici le body de votre post. Vous allez parsemer celui si de bouts d&#8217;xml qui seront process par BeautifulSoup et Improved-Inlines et qui seront transformés en html (grâce à un template).</p>
<p>L&#8217;exemple le plus simple est :</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inline</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;media.photo&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>qui affichera l&#8217;objet de pk 1 qui est modélisé par la classe photo contenu dans l&#8217;app media.</p>
<p>Mais vous pourrez également utiliser les attributs xml suivant :<br />
ids pour afficher plusieurs id, séparées par des virgules.<br />
filter pour passer un filtre django<br />
template pour choisir le template django qui sera utilisé (par défault l&#8217;app utilise inlines/app_model.html)<br />
class qui permet de passer une class au template</p>
<p>ce qui donnerait :</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inline</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;calendar.event&quot;</span> <span style="color: #000066;">filter</span>=<span style="color: #ff0000;">&quot;date__gte=datetime.date.today()&quot;</span> <span style="color: #000066;">template</span>=<span style="color: #ff0000;">&quot;calendar/event_inline.html&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>ou encore :</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inline</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;app.model&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;&lt;some pk&gt;</span></span>&quot;/&gt; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inline</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;app.model&quot;</span> <span style="color: #000066;">ids</span>=<span style="color: #ff0000;">&quot;&lt;some pk&gt;</span></span>,<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;some</span> other pk<span style="color: #000000; font-weight: bold;">&gt;</span></span>&quot; /&gt;</div></div>
<h1>4-Conclusion</h1>
<p>Je n&#8217;ai pas encore eu l&#8217;occasion de m&#8217;amuser, &#8216;pour de vrai&#8217; avec cette appli toute simple, ce n&#8217;est pas l&#8217;envie qui m&#8217;en manque parce que je pense lui trouver une foule d&#8217;application qui me faciliteront grandement la vie.<br />
J&#8217;ai une seule petite appréhension que le process par BeautifulSoup ne ralentisse pas quelque peu le rendering des pages. Ca serait d&#8217;ailleurs un ralentissement à évaluer. En tout cas, amusez vous bien avec cette appli aussi simple, qu&#8217;utile.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/06/20/django-improved-inlines-enrichissez-facilement-vos-contenus-et-ca-sans-payer-lisf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django-samaritan, parce que tout le monde a le droit d&#8217;aimer Bruce Willis</title>
		<link>http://j-mad.com/blog/2010/05/23/django-samaritan-parce-que-tout-le-monde-a-le-droit-daimer-bruce-willis/</link>
		<comments>http://j-mad.com/blog/2010/05/23/django-samaritan-parce-que-tout-le-monde-a-le-droit-daimer-bruce-willis/#comments</comments>
		<pubDate>Sun, 23 May 2010 17:52:58 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[La Django-app du mois]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=604</guid>
		<description><![CDATA[
			
				
			
		
Le mois de mai est toujours un mois compliqué. Normalement c&#8217;est à cause de tout ces jours fériés qui sont autant d&#8217;obstacle au travail et qui nous oblige à être tout le temps en retard en mai. Pourtant, cette année, malgré que deux des jours fériés de mai tombent un samedi et que le dernier [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F05%2F23%2Fdjango-samaritan-parce-que-tout-le-monde-a-le-droit-daimer-bruce-willis%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F05%2F23%2Fdjango-samaritan-parce-que-tout-le-monde-a-le-droit-daimer-bruce-willis%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p style="padding-left: 30px;"><a href="http://j-mad.com/blog/wp-content/uploads/2010/05/le.dernier.samaritain.jpg" rel="thumbnail"><img class="alignleft size-medium wp-image-603" style="border: 1px solid black; margin-left: 10px; margin-right: 10px;" title="Le Dernier Samaritain" src="http://j-mad.com/blog/wp-content/uploads/2010/05/le.dernier.samaritain-214x300.jpg" alt="" width="151" height="212" /></a>Le mois de mai est toujours un mois compliqué. Normalement c&#8217;est à cause de tout ces jours fériés qui sont autant d&#8217;obstacle au travail et qui nous oblige à être tout le temps en retard en mai. Pourtant, cette année, malgré que deux des jours fériés de mai tombent un samedi et que le dernier (demain) soit un jour travaillé pour moi, la malédiction du mois de mai a encore frappé et je n&#8217;ai de temps pour rien&#8230; A croire que c&#8217;est le mois de mai lui-même qui a pour conséquence que l&#8217;on soit en retard. La malédiction sanglante du mois de mai … (tiens on pourrait faire un bon film de série B avec ça). Enfin, tout ça pour expliquer le fait que l&#8217;application du mois que j&#8217;ai choisi est une toute petite application, que je n&#8217;ai en fait pas eu l&#8217;occasion d&#8217;essayer &#8216;en vrai&#8217;.  (et puis bon, je n&#8217;allais pas cracher sur la possibilité de faire un jeu de mot coolos en parlant d&#8217;un film que j&#8217;adore …)</p>
<p style="padding-left: 30px;">
<p style="padding-left: 30px;">
<p style="padding-left: 30px;">
<p style="padding-left: 30px;">
<h1>1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?</h1>
<p>On le trouve sur la page <a href="http://github.com/benslavin/django-samaritan">github</a> qui va bien et c&#8217;est tout. Quand à la doc, elle est, elle aussi uniquement sur le github</p>
<p>La doc se découpe d&#8217;ailleurs entre :</p>
<ul>
<li> le Readme</li>
<li> le Install</li>
<li> les commentaires dans le code.</li>
</ul>
<p>C&#8217;est peu vous aller me dire, mais vu que l&#8217;app fait, en tout et pour tout, moins de 200 lignes, c&#8217;est suffisant.</p>
<h1>2- A quoi ca sert ?</h1>
<p>A remplacer le model django.contrib.auth.models.User par un des siens, d&#8217;une façon propre. Pour aider encore plus, des models spéciaux de M2M, de OnetoOne et de FK sont fournis pour quand on voudra créer des références vers nos nouveaux users.</p>
<h1>3- Comment ça marche ?</h1>
<p>Il y a deux façons possibles de le faire marcher.</p>
<p>En l&#8217;installant puis en l&#8217;utilisant. Tout simplement.. On créé son model, on utilise la fonction get_user_model() qui est fournit avec django-samaritain (ou en utilisant directement notre model d&#8217;ailleurs). Et on utilise les spécialisations des FK,OtO et M2M.</p>
<p>En utilisant la méthode de Monkey Patching pour injecter à la volée le comportement de django-samaritan dans un projet existant. Cette deuxième méthode est déconseillée pour une utilisation à long terme,dixit l&#8217;auteur de l&#8217;app lui même.</p>
<h1>3- Retour ?</h1>
<p>Et oui, je sais, c&#8217;est un comble. Mais bon, c&#8217;est mes billets, alors je fais ce que je veux. Donc, si l&#8217;un de vous a des retours sur l&#8217;utilisation de cette app, je suis bien entendu preneur, ne vous gênez surtout pas.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/05/23/django-samaritan-parce-que-tout-le-monde-a-le-droit-daimer-bruce-willis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Djangocong ,bilan perso d&#8217;un gentil organisateur.</title>
		<link>http://j-mad.com/blog/2010/04/27/djangocong-bilan-perso-dun-gentil-organisateur/</link>
		<comments>http://j-mad.com/blog/2010/04/27/djangocong-bilan-perso-dun-gentil-organisateur/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 12:29:45 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[De tout et de rien]]></category>
		<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=581</guid>
		<description><![CDATA[
			
				
			
		
Poussé par les nombreux bilans que je vois fleurir sur le hastag #djangocong, je ne peux que participer et faire mon bilan perso de ce week-end de folie, (et comme je suis à la bourre, je le fais en dégustant mon jambon-beurre salé du midi).
Je ferrais un bilan plus &#8216;du coté de l&#8217;organisateur&#8217; parce que [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F27%2Fdjangocong-bilan-perso-dun-gentil-organisateur%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F27%2Fdjangocong-bilan-perso-dun-gentil-organisateur%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Poussé par les nombreux bilans que je vois fleurir sur le hastag <a href="http://twitter.com/#search?q=%23djangocong">#djangocong</a>, je ne peux que participer et faire mon bilan perso de ce week-end de folie, (et comme je suis à la bourre, je le fais en dégustant mon jambon-beurre salé du midi).</p>
<p>Je ferrais un bilan plus &#8216;du coté de l&#8217;organisateur&#8217; parce que des bilans &#8216;coté public&#8217; il y en a déjà eu plein et des super complets, bien plus que ce que je pourrais faire (comme celui de <a href="http://blog.providenz.fr/2010/04/djangocong-retour-sur-les-rencontres-django-a-marseille/">laurent</a> mais aussi de tous les autres présents, une simple recherche sur le hastag donnera tout les liens).</p>
<p>Pour commencer, les remerciements :</p>
<ul>
<li>à <a href="http://www.biologeek.com">David</a> bien entendu, parce que voilà, y aurait pas eu de djangocong sans david.</li>
<li>à <a href="http://github.com/samueladam">Samuel</a> pour la vidéo et les bières belges, toujours aussi bonnes (je ne citerais pas de noms, même sous la torture (je dirais juste qu&#8217;il sait super bien manier un aspirateur), mais certains présents sont d&#8217;ailleurs tombés amoureux de certaines bières …)</li>
<li>à <a href="http://www.0d.be/">Fred</a>, pour avoir transporter son matos depuis la Belgique et nous avoir permis d&#8217;avoir des prises sons pour toutes les confs.</li>
<li>à <a href="http://blog.providenz.fr/">Laurent</a> pour les <a href="http://www.flickr.com/photos/providenz/sets/72157623931169122/">photos</a>, très réussies,</li>
<li>à <a href="http://twitter.com/arcagenis">Johann</a> qui oui a milité pour la création d&#8217;une asso, a réalisé de super tee-shirt dans un délai plus que court. (d&#8217;ailleurs il en reste quelqu&#8217;un à vendre, si vous voulez&#8230;.)</li>
<li>à <a href="http://agopian.info/">Matthieu</a> qui s&#8217;est occupé de tout plein de petits trucs tout le temps, quand on se demandait bien comment on allait faire, comme par exemple des badges (qui a remarqué que le poney django était en filigramme très clair sur la partie blanche des badges?), mais qui aussi passe l&#8217;aspirateur comme personne.</li>
<li>À <a href="http://twitter.com/daks_">Daks</a> pour avoir bossé sur le petit feuillet programme/info importantes et l&#8217;avoir imprimé en nombre.</li>
<li>à la <a href="http://tamblague.canalblog.com/">chérie de David</a> qui a réalisé la <a href="http://rencontres.django-fr.org/djangocong-pony.svg">mascotte</a> des Congs</li>
<li>à ma chérie qui m&#8217;a aidé sur les recherches de lieu (si vous avez eu des hotels où dormir, c&#8217;est grâce à elle <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</li>
<li>à Marseille Innovation, le propriétaire des salles qui m&#8217;a fait confiance (bon j&#8217;ai du un peu jouer au chat de Shrek) et nous a permis d&#8217;avoir un événement gratuit en me prêtant les salles pour le week-end avec pour seule condition de ne rien dégrader et de les rendre aussi propre que ce que je les avais reçu.</li>
<li>Aux généreux donateurs</li>
<li>À tout les conférenciers pour avoir fait des conférences de qualité, vivantes, et carrément cools.</li>
<li>À tout les présents, pour avoir été là, avoir donné la chance à cette première fois, avoir fait des centaines de kilomètre en train, voiture,  avions, vélos.</li>
<li>à la météo de dimanche qui nous a permis de manger au soleil.</li>
</ul>
<p>Pour le reste.</p>
<p>J&#8217;ai adoré ces deux jours de conférences. Et j&#8217;ai vraiment adoré les organiser. Que ce soit avant ou pendant. Plein de moment de stress (&#8216;mais où va-t-on trouver un resto pour ce soir?&#8217;) ou de petits moment fun (comme appeler un resto pour lui dire &#8216;bon je vous réserve l&#8217;intégralité de vos couverts&#8217; ).</p>
<p>Effectivement vouloir être intervenant en étant organisateur, ce fut une gageure qui fut difficile à tenir. Faire des slides entre minuit et deux heures du mat, pendant la nuit de samedi à dimanche (vous pouvez les trouver là ou sur slideshare), c&#8217;était rigolo mais fatiguant. Mais d&#8217;un autre coté, je suis content d&#8217;avoir pu parler un peu, d&#8217;un sujet qui me tenait à cœur, même si j&#8217;aurais voulu faire mieux, pour le coup.</p>
<p>Donc oui, voir que tout ce passait plutôt bien, que tout le monde était content, heureux d&#8217;être venu, fut une vraie joie et autant le dire tout de suite, une vraie motivation pour se dire qu&#8217;il faut faire un truc l&#8217;année prochaine (oui, je sais david, il faut débrieffer et qu&#8217;on en discute, tout ça,&#8230;. <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</p>
<p>Bien entendu il y a des choses à améliorer. Pour les repas, on a dérapé à chaque fois au niveau du planning prévu. Faut il passer sur une pause de 2h pour le repas, prévoir un traiteur ou trouver une troisième solution, il faudra étudier le truc.</p>
<p>Pour les conférences, elles furent effectivement super denses, s&#8217;enchainant à toute allure sans trop de pause. Est ce qu&#8217;il faut réduire le temps des confs, en faire moins, prévoir plus que deux jours de congs.. là aussi il y a plein de pistes à explorer (l&#8217;idée de david de partir sur un format un peu plus barcamp me semble une idée très intéressante) .</p>
<p>Laisser plus de place à des sprint code pourrait être intéressant aussi, à voir comment on mixe les eux. Plein de possibilité donc, pour la prochaine édition, si elle a lieu (ben quoi laissons un peu le suspense planer:) )</p>
<p>Au niveau logistique, plein de petit truc à améliorer pour la prochaine, David en a listé par mal, je rajouterais de prévoir plus de cafetière (au moins deux) pour pouvoir étancher plus facilement la soif des intervenants et ne pas faire confiance aux bus marseillais le dimanche matin <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Je suis sur qu&#8217;en se posant et en réfléchissant on trouvera d&#8217;autre petit trucs pour améliorer la logistique.</p>
<p>Créer l&#8217;asso, on s&#8217;y est un peu engagé au tout début des deux jours, et ça sera un pré-requis obligatoire, pour la deuxième édition, je pense.</p>
<p>Donc voilà, pour moi, c&#8217;est deux jours furent vraiment un plaisir de chaque instant.</p>
<p>Le dimanche soir, lorsque je me suis retrouvé seul dans le bâtiment, à vérifier une dernière fois que tout était niquel, en ordre, bien rangé, juste avant de charger le carton de cadavre de bière pour aller le jeter au recyclage, il faut bien avouer que j&#8217;ai eu un petit pincement au coeur en me disant &#8216;c&#8217;est déjà fini&#8217;.</p>
<p>Et puis je me suis dit &#8216;vivement l&#8217;année prochaine pour la deuxième édition&#8217;.</p>
<p>Alors voilà.</p>
<h2>A l&#8217;année prochaine, pour de nouvelles aventures, qu&#8217;elles qu&#8217;en soient leur formes.</h2>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/04/27/djangocong-bilan-perso-dun-gentil-organisateur/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Titanium par l&#8217;exemple, un client twitter en dix minutes.</title>
		<link>http://j-mad.com/blog/2010/04/11/titanium-par-lexemple-un-client-twitter-en-dix-minutes/</link>
		<comments>http://j-mad.com/blog/2010/04/11/titanium-par-lexemple-un-client-twitter-en-dix-minutes/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 22:19:46 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[Titanium]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=565</guid>
		<description><![CDATA[
			
				
			
		
Bon, bien entendu mon titre est volontairement accrocheur. Et complètement mensonger. Mais il faut bien appâter le chaland un peu. Sinon, je ne serais jamais un blogueur influent.. Alors vive les titres accrocheur  
Mais avant de commencer, il faut peut-être que j&#8217;explique ce que c&#8217;est que Titanium. Titanium c&#8217;est un framework assez génial (et [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F11%2Ftitanium-par-lexemple-un-client-twitter-en-dix-minutes%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F11%2Ftitanium-par-lexemple-un-client-twitter-en-dix-minutes%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Bon, bien entendu mon titre est volontairement accrocheur. Et complètement mensonger. Mais il faut bien appâter le chaland un peu. Sinon, je ne serais jamais un blogueur influent.. Alors vive les titres accrocheur <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Mais avant de commencer, il faut peut-être que j&#8217;explique ce que c&#8217;est que <a href="http://www.appcelerator.com/">Titanium</a>. Titanium c&#8217;est un framework assez génial (et libre) qui permet de faire du dev iphone/android en html/javascript. Histoire que ceux qui n&#8217;aiment ni l&#8217;objective-C, ni le Java puisse tout de même coder sur ces plateformes là. Histoire aussi de coder qu&#8217;une fois son appli et de la voir tourner sur les deux.</p>
<p>Là, vous devez être en train de vous demander : &#8216;Il va nous parler de dev iphone/android en js ? &#8216;</p>
<p>Et ben en fait, pas du tout.</p>
<p>Parce que là où Titanium est encore plus génial, c&#8217;est que l&#8217;on peut coder pour le Desktop aussi, en multiplateforme à savoir Linux, OSX et Windows. Sympa, vous aller me dire, mais bon faire toute une appli desktop en js, voilà quoi …</p>
<p>Oui, mais non, parce que pour le desktop, on peut coder en python (attention en python 2.5 uniquement), en ruby ou.. misère, en php. Et là, ça devient carrément miam.</p>
<p>Ca faisait donc plusieurs mois que j&#8217;avais envie de tester le bouzin, mais bon, j&#8217;avais déjà pas le temps de bosser sur histoiresderolistes.com alors tester un truc en plus&#8230; Et puis les tests c&#8217;est bien joli mais pour faire des Hello World! Merci.</p>
<p>Mais comme les vacances, ce n&#8217;est pas fait que pour travailler sur le boulot en retard, j&#8217;ai pu m&#8217;y mettre, un peu. (et puis faut avouer que <a href="http://sebastien.porati.me/blog/2010/04/dailyquote-application-iphone-android-avec-titanium/">le billet</a> de <a href="http://twitter.com/popofr13">@popofr13</a> sur le dev titanium iphone m&#8217;a boosté à écrire le mien). Restait alors le problème du Hello World. Après 30 secondes de réflexion je me suis dit que bidouiller des trucs avec twitter, ça serait rigolo. Et en plus comme c&#8217;est bien buzz word twitter, ça plaira, c&#8217;est sur.</p>
<p>Et c&#8217;est ainsi qu&#8217;un froid jour d&#8217;avril, une nouvelle catégorie d&#8217;article naquit sur le j-mad blog. Une catégorie dédiée aux bidouillages avec Titanium et ayant pour fil rouge le dev d&#8217;un client twitter basique (type Pino quoi). Et comme pour chaque projet, il faut un nom, j&#8217;en ai trouvé un TwittPouick. Oui je sais. Non, pas de commentaires sur le nom.</p>
<h1>1- La genèse, installation et création du projet.</h1>
<p>Alors c&#8217;est tout simple, pour télécharger Titanium, on va sur le site et on clique sur <a href="http://www.appcelerator.com/products/download/">téléchargement</a>.</p>
<p>Ensuite il n&#8217;y a qu&#8217;à décompresser l&#8217;archive et lancer l&#8217;installateur. Petite précision, il y a assez régulièrement de nouvelle version, qui sont indiqués directement dans l&#8217;interface de Titanium. Il suffit alors de relancer le cycle dl/décompression/installation.</p>
<p>Une fois Titanium installé et lancé, il suffit de cliquer sur New Project pour voir la fenêtre ci dessous apparaître. Rien de bien difficile à comprendre, il suffit de remplir les champs et de cliquer sur create project (N&#8217;oubliez pas de cocher en vert la petite case python tout de même).</p>
<p><a href="http://j-mad.com/blog/wp-content/uploads/2010/04/new_project.png" rel="thumbnail"><img class="aligncenter size-medium wp-image-566" title="new_project" src="http://j-mad.com/blog/wp-content/uploads/2010/04/new_project-300x169.png" alt="" width="300" height="169" /></a></p>
<p>Vous arrivez ensuite sur la fenêtre principale composé d&#8217;à gauche la liste de vos projets (sur mon screen on voit d&#8217;ailleurs mon projet twittpouick) et à droite ben la zone de droite avec un menu horizontal en haut Dashboard / Edit / Test &amp; Package.</p>
<p><a href="http://j-mad.com/blog/wp-content/uploads/2010/04/main.png" rel="thumbnail"><img class="aligncenter size-medium wp-image-567" title="main" src="http://j-mad.com/blog/wp-content/uploads/2010/04/main-300x169.png" alt="" width="300" height="169" /></a></p>
<ul>
<li>Le premier ne sert à rien, c&#8217;est simplement la liste des options en fonction de si on a un abonnement payant ou pas.</li>
<li>L&#8217;onglet Edit sert un peu plus, il permet de modifier les infos que l&#8217;on a saisit à la création du projet</li>
<li>Enfin Test &amp; Package sera celui sur lequel vous allez passer le plus de temps, vu que c&#8217;est à partir de là que vous lancerez votre projet. (et qu&#8217;un jour quand il sera fini vous le packagerait et tout et tout)</li>
</ul>
<h1>2- Et ensuite ?</h1>
<p>Ben ensuite, on prend son navigateur de fichier favori et on va voir ce qu&#8217;il nous à générer le tonton Titanium.<br />
Et l&#8217;on voit ça :</p>
<p style="text-align: left;"><a href="http://j-mad.com/blog/wp-content/uploads/2010/04/fichiers.png" rel="thumbnail"><img class="size-full wp-image-568 aligncenter" title="fichiers" src="http://j-mad.com/blog/wp-content/uploads/2010/04/fichiers.png" alt="" width="259" height="309" /></a></p>
<p>Bon le fichier jquery n&#8217;est pas là de base, c&#8217;est moi qui l&#8217;est rajouté. Vous comprendrez pourquoi par la suite.</p>
<p>Donc il ne devrait y avoir quasiment que le fichier index.html. Qui correspond à notre fenêtre principale. Avant de partir pour de vrai dans des vrais choses rigolotes (comprendre le client twitter), on va tout de même faire un hello word. Et oui.</p>
<p>Ouvrez le fichier index.html et remplacez son contenu par celui-ci</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&lt;</span>html<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>head<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>script <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;text/python&quot;</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> hello_python<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Hello World&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/script<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/head<span style="color: #66cc66;">&gt;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>body <span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>div <span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>div <span style="color: #66cc66;">&gt;</span>Le Hello World<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>button onclick=<span style="color: #483d8b;">&quot;alert(hello_python())&quot;</span><span style="color: #66cc66;">&gt;</span>Bouton Hello<span style="color: #66cc66;">&lt;</span>/button<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/body<span style="color: #66cc66;">&gt;</span><br />
<span style="color: #66cc66;">&lt;</span>/html<span style="color: #66cc66;">&gt;</span></div></div>
<p>Allez dans Test &amp; Package, cliquez sur Launch App, une fenêtre blanche se lance avec un bouton, cliquez sur le bouton et mirage, une fenêtre Alert javascript s&#8217;affiche avec un Hello World dedans.</p>
<p>Ce qui est logique, si on regarde le code au dessus. On crée une section de code python, on définit une fonction que l&#8217;on appelle sur le onclick du bouton, dans un code js donc, et on passe le retour de la fonction python (je le rappelle) en paramètre à la fonction alert js.</p>
<p>En fait cet exemple, bien que très simple, montre la plupart des trucs génials de Titanium.</p>
<p>On peut déclarer des sections de code python, directement dans les fichiers html (mais on peut le faire proprement en dehors aussi, ça sera l&#8217;objet d&#8217;un prochain billet) et on peut accéder au python du js.</p>
<p>Et c&#8217;est aussi valable dans l&#8217;autre sens. On peut accéder du python, à du code JS. Que ce soit accéder à des fonctions ou à des variables, que l&#8217;on peut modifier, bien entendu (à ce propos, cette <a href="https://developer.appcelerator.com/doc/desktop/python">page de la doc officielle</a> explique la conversion entre les types python / javascript.</p>
<h1>3- Et TwittPouick naquit.</h1>
<p>Pour clore ce premier billet, déjà bien long, et justifier un peu, le titre du billet, on va faire une premier truc, c&#8217;est récupérer, après clic sur un bouton, sa timeline, dans un mode code grouirk, parce que c&#8217;est juste pour finir en beauté ce billet.</p>
<h2>3.1 Récupération de sa timeline.</h2>
<p>Je ne connais pas les librairies twitter en python. Et je n&#8217;ai pas vraiment le temps de me plonger dedans pour voir laquelle est la mieux. Par contre je connais bien <a href="http://benoitc.github.com/restkit/index.html">restkit</a>, une librairie bien bien sympa de <a href="http://twitter.com/benoitc">@benoitc</a> et qui marche plutôt bien.</p>
<p>On va donc l&#8217;utiliser pour récupérer sa timeline.</p>
<h2>3.2 Affichage de sa timeline.</h2>
<p>On à une interface HTML. On veut modifier le dom. Moi j&#8217;aime bien jquery. Donc on va utiliser Jquery. Directement dans du code python. Et oui. Comme si on était en Js. Sauf que l&#8217;on ne pourra pas utiliser le raccourci $ , vu qu&#8217;on est en python. On va donc simplement utiliser le vrai objet JQuery.</p>
<h2>3.3 Utilisation des API Titanium</h2>
<p>On peut bien entendu, encore heureux, utiliser directement les API titanium qui sont en Js. Pour l&#8217;exemple, j&#8217;utilise Titanium.API.info qui permet d&#8217;afficher une chaîne de caractère dans la console.</p>
<p>Bon et maintenant le code, complet, du fichier index.html</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&lt;</span>html<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>head<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>link rel=<span style="color: #483d8b;">&quot;stylesheet&quot;</span> <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;text/css&quot;</span> href=<span style="color: #483d8b;">&quot;style.css&quot;</span> /<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>link rel=<span style="color: #483d8b;">&quot;stylesheet&quot;</span> <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;text/css&quot;</span> href=<span style="color: #483d8b;">&quot;color.css&quot;</span> /<span style="color: #66cc66;">&gt;</span> &nbsp; &nbsp;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>script <span style="color: #008000;">type</span> =<span style="color: #483d8b;">&quot;text/javascript&quot;</span> src=<span style="color: #483d8b;">&quot;jquery-1.3.2.js&quot;</span><span style="color: #66cc66;">&gt;&lt;</span>/script<span style="color: #66cc66;">&gt;</span><br />
<br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>script <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;text/python&quot;</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> getTimelineJquery<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> restkit <span style="color: #ff7700;font-weight:bold;">import</span> Resource, BasicAuth<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> pyquery <span style="color: #ff7700;font-weight:bold;">import</span> PyQuery <span style="color: #ff7700;font-weight:bold;">as</span> pq<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">import</span> simplejson <span style="color: #ff7700;font-weight:bold;">as</span> json<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">import</span> json <span style="color: #808080; font-style: italic;"># py2.6 only</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">class</span> TwitterTimeline<span style="color: black;">&#40;</span>Resource<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, pool_instance=<span style="color: #008000;">None</span>, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_url = <span style="color: #483d8b;">&quot;https://api.twitter.com/1/statuses/&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; auth = BasicAuth<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;TwitterUserName&quot;</span>, <span style="color: #483d8b;">&quot;TwitterPassword&quot;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>TwitterTimeline, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span>search_url, follow_redirect=<span style="color: #008000;">True</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; max_follow_redirect=<span style="color: #ff4500;">10</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pool_instance=pool_instance,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;filters=<span style="color: black;">&#91;</span>auth<span style="color: black;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> get_timeline<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'home_timeline.json'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resp = <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>TwitterTimeline, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> json.<span style="color: black;">loads</span><span style="color: black;">&#40;</span>resp.<span style="color: black;">body</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s = TwitterTimeline<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tl = s.<span style="color: black;">get_timeline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> item <span style="color: #ff7700;font-weight:bold;">in</span> tl :<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = u<span style="color: #483d8b;">&quot;&quot;&quot;&lt;p class=&quot;p_tweet color_p_tweet&quot;&gt; %s : &nbsp;%s&lt;/p&gt;&quot;&quot;&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>item<span style="color: black;">&#91;</span><span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'screen_name'</span><span style="color: black;">&#93;</span>, item<span style="color: black;">&#91;</span><span style="color: #483d8b;">'text'</span><span style="color: black;">&#93;</span> <span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Titanium.<span style="color: black;">API</span>.<span style="color: black;">info</span> <span style="color: black;">&#40;</span>element<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jQuery<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;#timeline&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>element<span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/script<span style="color: #66cc66;">&gt;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/head<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>body <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;body color_body&quot;</span><span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&lt;</span>div<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>h1<span style="color: #66cc66;">&gt;</span>Votre timeline avec TwittPouick<span style="color: #66cc66;">&lt;</span>/h1<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>button onclick=<span style="color: #483d8b;">&quot;getTimelineJquery()&quot;</span><span style="color: #66cc66;">&gt;</span> Get Timeline Jquery <span style="color: #66cc66;">&lt;</span>/button<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>div <span style="color: #008000;">id</span>=<span style="color: #483d8b;">&quot;timeline&quot;</span><span style="color: #66cc66;">&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span>/body<span style="color: #66cc66;">&gt;</span><br />
<span style="color: #66cc66;">&lt;</span>/html<span style="color: #66cc66;">&gt;</span></div></div>
<p>Vous n&#8217;avez plus qu&#8217;à installer restkit (avec easy_install), pour python 2.5 N&#8217;OUBLIEZ PAS !!!, mettre jquery à coté de votre fichier index.html, mettre votre login / mot de passe twitter et puis lancer l&#8217;appli twitter.</p>
<p>Cliquer sur le bouton, quelque seconde après .. miracle les tweets apparaissent. Recliquez sur le bouton, les nouveaux twitts s&#8217;ajoutent en bas de liste&#8230;.</p>
<p>Et voilà, même pas 10 minutes et déjà vous avez un début de client. Comme quoi, je ne vous avais pas tant mené en bateau que ça, dans mon titre, finalement.</p>
<h1>4- Conclusion.</h1>
<p>Ce premier billet, n&#8217;est qu&#8217;un premier billet. Il ne va pas très loin dans la présentation de Titanium, parce que je n&#8217;ai pas vraiment eu le temps de moi même faire plus. Vivement les prochains billets donc. Enfin, j&#8217;espère que c&#8217;est ce que vous vous dites en ce moment <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .<br />
Pour la suite, je mettrais en place un repository mercurial sur bitbucket où je déposerais les différentes étapes de la création de TwittPouick.</p>
<p>En attendant mon prochain billet, amusez vous bien avec Titanium.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/04/11/titanium-par-lexemple-un-client-twitter-en-dix-minutes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Django-request , ne partez plus en quest de vos stats</title>
		<link>http://j-mad.com/blog/2010/04/10/django-request-ne-partez-plus-en-quest-de-vos-stats/</link>
		<comments>http://j-mad.com/blog/2010/04/10/django-request-ne-partez-plus-en-quest-de-vos-stats/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 16:44:54 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[La Django-app du mois]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=559</guid>
		<description><![CDATA[
			
				
			
		
Et non, vous ne rêvez pas, on est même pas le 15 avril et déjà, déjà, le billet de l&#8217;app django du mois est là. Mais bon, les rencontres django ayant lieu dans maintenant 14 jours et n&#8217;ayant pas encore commencer à préparer ma conf, même pas le premier mot (enfin si, bonjour), ce qui [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F10%2Fdjango-request-ne-partez-plus-en-quest-de-vos-stats%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F10%2Fdjango-request-ne-partez-plus-en-quest-de-vos-stats%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Et non, vous ne rêvez pas, on est même pas le 15 avril et déjà, déjà, le billet de l&#8217;app django du mois est là. Mais bon, les <a title="DjangoCong" href="http://rencontres.django-fr.org/">rencontres django</a> ayant lieu dans maintenant 14 jours et n&#8217;ayant pas encore commencer à préparer ma conf, même pas le premier mot (enfin si, bonjour), ce qui fait que je suis &#8216;dans la banade&#8217;, comme l&#8217;a fait si justement remarquer il y a peu <a href="http://twitter.com/daks_">@daks_</a></p>
<p>Donc, je préfère me &#8216;débarrasser&#8217; tout de suite de l&#8217;app du mois, comme ça, ça sera au moins une chose de faite.</p>
<p>Ce mois-ci, je vais donc vous présenter django-request, une app pour faire des stats sur la fréquentation de votre django. Oui je sais il y a google analytics pour ça. Mais bon, on sait jamais, ça peut être utile quand même.</p>
<h1>1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?</h1>
<p>On le trouve à deux endroits :</p>
<ul>
<li>sur le <a href="http://github.com/kylef/django-request">github</a> qui va bien</li>
<li>sur les <a href="http://kylefuller.co.uk/projects/django-request/">pages dédiées sur le site de son auteur</a>.</li>
</ul>
<p>A noter que quasiment toute la doc se trouve être sur la partie dédiée à django-request sur le site de son auteur.</p>
<p>Pour l&#8217;installation, facile, un git clone, un téléchargement de source ou alors pip et easy_install.</p>
<p>Quand à la doc, elle est vraiment très fournie et complète, permettant d&#8217;installer, de configurer, d&#8217;utiliser, la totale quoi.</p>
<h1>2- A quoi ca sert ?</h1>
<p>Ben à faire des stats, je l&#8217;ai déjà dit. Qui ne seront visibles que dans la partie admin.</p>
<p>On peut avoir de jolis graphiques concernant :</p>
<ul>
<li>les visiteurs uniques</li>
<li>les visites basées sur des referrer différents</li>
<li>les requêtes reçues par le serveur</li>
<li>les requêtes venant des moteur de recherches</li>
<li>les requêtes provenant du javascript</li>
<li>les requêtes en SSL</li>
<li>les requêtes faites par un utilisateur</li>
<li>le nombre d&#8217;erreur 404</li>
<li>le nombre d&#8217;erreur, toutes erreurs comprises</li>
<li>le nombre d&#8217;utilisateur enregistré sur le site qui ont fait des requêtes</li>
</ul>
<p>Par défaut les calculs seront fait pour les visiteurs uniques, les visites en fonctions des referrers et le nombre global de requêtes.</p>
<p>On obtient ensuite un joli petit graphique qui nous donne tout plein d&#8217;infos. Et plein de petits tableaux pour en avoir encore plus.</p>
<p><a href="http://j-mad.com/blog/wp-content/uploads/2010/04/graph_django_requests.png" rel="thumbnail"><img class="aligncenter size-full wp-image-560" title="graph_django_requests" src="http://j-mad.com/blog/wp-content/uploads/2010/04/graph_django_requests.png" alt="" width="480" height="272" /></a></p>
<p>Et on peut même avoir, des petits templates tags pour voir les users actifs sur le site</p>
<h1>3- Comment ça marche ?</h1>
<p>Il suffit d&#8217;ajouter &#8216;request&#8217; dans ses installed_apps et d&#8217;ajouter le middleware qui va bien. (Attention suivant les middlewares déjà installés, la position du middleware de django-request, dans le tuple des middleware est importantt, mais c&#8217;est bien expliqué dans la doc).</p>
<p>Ensuite, tout ce passe dans l&#8217;interface d&#8217;admin</p>
<h1>4- Tips de chez Jmad.</h1>
<p>Quand j&#8217;ai installé le tout avec easy_install, j&#8217;ai oublié de rajouter les chemins pour avoir les templates admins de l&#8217;app. Résultat je n&#8217;avais rien dans l&#8217;admin. Faites y attention ou alors installez request directement dans votre projet django, comme une de vos apps.</p>
<p>Le model Request présente un champ language qui est modélisé en bd par un varchar de 25. Avec mes tests, cette longueur était bien trop petite pour mon firefox. Du coup boum une erreur BD a base de &#8216;machin qui a été truncated&#8217;. J&#8217;ai passé la taille du champ à 200 pour être tranquille.</p>
<p>Les différents fichiers js qui sont utilisés sont bien entendu fournis. Pourtant par défaut, les templates vont utilisés ceux hostés ailleurs (sur le site web de l&#8217;auteur par exemple). N&#8217;oubliez pas de changer cette option si cela vous dérange.</p>
<p>C&#8217;est expliqué dans la doc, mais je le redis ici. Une fois que tout est bien configuré, pour aller voir ces stats, vous allez dans l&#8217;admin, vous cliquez sur la ligne Request de l&#8217;app Request. Là vous avez la liste de toutes les requêtes. (pas très utile là comme ça, vous me direz). Levez les yeux, en haut à droie, à coté du bouton Add Request, vous avez un bouton Overview. Et voilà, cliquez, vous avez vos stats.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/04/10/django-request-ne-partez-plus-en-quest-de-vos-stats/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Lancement d&#8217;un side project : Histoiresderolistes.com</title>
		<link>http://j-mad.com/blog/2010/04/05/lancement-dun-side-project-histoiresderolistes-com/</link>
		<comments>http://j-mad.com/blog/2010/04/05/lancement-dun-side-project-histoiresderolistes-com/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 11:51:46 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[H2Rôlistes]]></category>
		<category><![CDATA[jdr]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[sideproject]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=549</guid>
		<description><![CDATA[
			
				
			
		
&#8216;C&#8217;est l&#8217;histoire d&#8217;un mec …&#8217; qui était rôliste.
Bon ok, c&#8217;était facile, mais je trouve que c&#8217;est une bonne façon de démarrer ce billet. Billet tout entier consacré à de l&#8217;autopromo ou plutôt à l&#8217;annonce du lancement d&#8217;un de mes side-project comme on dit.
Histoiresderolistes.com. Né d&#8217;une idée toute simple à savoir que les rôlistes, dont je [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F05%2Flancement-dun-side-project-histoiresderolistes-com%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F05%2Flancement-dun-side-project-histoiresderolistes-com%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>&#8216;C&#8217;est l&#8217;histoire d&#8217;un mec …&#8217; qui était rôliste.</p>
<p>Bon ok, c&#8217;était facile, mais je trouve que c&#8217;est une bonne façon de démarrer ce billet. Billet tout entier consacré à de l&#8217;autopromo ou plutôt à l&#8217;annonce du lancement d&#8217;un de mes side-project comme on dit.</p>
<p><a title="racontez vos histoires de rôlistes" href="http://histoiresderolistes.com/">Histoiresderolistes.com</a>. Né d&#8217;une idée toute simple à savoir que les rôlistes, dont je suis, adorent se raconter leur vieilles histoires de joueurs, leurs souvenirs de catastrophe évitées ou de justesse, ou pas du tout, leur grand moment de rigolade. Et parfois on a envie de partager ces histoires, pas seulement avec son groupe de joueur actuel, mais avec ses anciens compagnons de parties, ou même avec d&#8217;autres rôlistes tout court.</p>
<p>Comme je n&#8217;ai pas trouvé un tel endroit, je me suis dit que j&#8217;allais la bâtir moi même, la petite taverne virtuelle où nous pourrions tous être barde, le temps d&#8217;une histoire.</p>
<p>Alors ce ne fut pas facile de venir à bout de ce projet, dont la taille est pourtant plus que petite. Pour donner une idée de la chronologie :</p>
<ul>
<li>j&#8217;ai eu l&#8217;idée du site en juillet 2009, j&#8217;ai aussitôt acheté le nom de domaine</li>
<li>j&#8217;ai commencé à aligner quelques lignes de code en aout (merci les vacances), mais ayant du boulot du boulot, en retard, j&#8217;ai que très peu avancé.</li>
<li>Je m&#8217;y suis vraiment mis fin janvier/début février en essayant de trouver du temps la nuit et les week-ends.</li>
<li>le week-end de Pâques m&#8217;a permis de finaliser le tout et de faire tester à quelques chanceux (merci les gens de #djangocong et du plug).</li>
</ul>
<p>Mais maintenant, il est en ligne, et vous pouvez aller y lire/raconter des histoires de rôlistes. Et si il est en ligne, c&#8217;est aussi grâce à ma chére et tendre qui a été la première des béta testeuses, bien qu&#8217;elle ne soit pas du tout rôliste&#8230; Le fait qu&#8217;il n&#8217;y est pas de fautes d&#8217;ortographes sur le site (ou presque pas) est par exemple complètement grâce à elle, mais ce n&#8217;est pas son seul apport, loin de là.</p>
<p>Et ce n&#8217;est pas qu&#8217;un &#8217;simple&#8217; site où les gens soumettent des histoires. Quitte à lancer un truc, autant s&#8217;en servir comme bac à sable, pour tester des choses dont je parle dans mes billets.</p>
<p>Comme par exemple, l&#8217;introduction de mécanismes tirés des jeux vidéos, comme les titres et succès (qui sont ici appelés badges).</p>
<p>Vous pourrez donc gagner des titres (top posteur par exemple) ou des badges comme le badge du djinn narcissique ou du gobelin fanatique (<a href="http://histoiresderolistes.com/badge/badges">liste des badges</a>). Exactement comme dans les jeux, vous ne connaitrez pas la manière de débloquer certains badges. Parfois même, vous ne saurez même pas que les badges existent avant de les débloquer.</p>
<p>Ce n&#8217;est bien entendu qu&#8217;un début, j&#8217;ai plein d&#8217;autres idées (dont certaines déjà listées dans les billet du ce blog), que je mettrais en place petit à petit. En essayant, ensuite, d&#8217;analyser le retour des utilisateurs à mes &#8216;expériences&#8217;.</p>
<p>Mais déjà, la question est de savoir si h2rolistes (et il y a même un <a href="http://twitter.com/h2rolistes">twitter</a> et un <a href="http://identi.ca/h2rolistes">identi.ca</a> pour suivre les nouveautés) va trouver son public ou non&#8230;</p>
<p>Et bien entendu, h2rolistes c&#8217;est du 100% <a href="http://www.djangoproject.com/">django</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/04/05/lancement-dun-side-project-histoiresderolistes-com/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Petit mémo concernant la syndication Django</title>
		<link>http://j-mad.com/blog/2010/04/03/petit-memo-concernant-la-syndication-django/</link>
		<comments>http://j-mad.com/blog/2010/04/03/petit-memo-concernant-la-syndication-django/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 09:03:49 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=546</guid>
		<description><![CDATA[
			
				
			
		
Ce billet n&#8217;est qu&#8217;un petit mémo rapide, pour éviter que d&#8217;autre perdent comme moi du temps à chercher un problème qui n&#8217;en est pas un. Si jamais je me trompe dans mon interprétation du problème et dans la solution que j&#8217;en donne, je suis preneur d&#8217;une explication / correctif dans les commentaires.
Django embarque, dans les [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F03%2Fpetit-memo-concernant-la-syndication-django%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F03%2Fpetit-memo-concernant-la-syndication-django%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Ce billet n&#8217;est qu&#8217;un petit mémo rapide, pour éviter que d&#8217;autre perdent comme moi du temps à chercher un problème qui n&#8217;en est pas un. Si jamais je me trompe dans mon interprétation du problème et dans la solution que j&#8217;en donne, je suis preneur d&#8217;une explication / correctif dans les commentaires.</p>
<p>Django embarque, dans les contrib, un petit framework pour géré la syndication. Plutôt bien foutu d&#8217;ailleurs.</p>
<p>Il fonctionne suivant un principe assez simple, pour chaque flux on définit une classe, ensuite on range les classes dans un dict où la clé sera le nom du flux dans l&#8217;url et la valeur, la classe, que l&#8217;on passe en paramètre à la vue qui gère l&#8217;ensemble des flux. (tout est parfaitement expliqué <a title="doc django syndication framework" href="http://docs.djangoproject.com/en/1.1/ref/contrib/syndication/#ref-contrib-syndication">dans la doc, ici</a>).</p>
<p>Par exemple :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> myproject.<span style="color: black;">feeds</span> <span style="color: #ff7700;font-weight:bold;">import</span> LatestEntries, LatestEntriesByCategory<br />
<br />
feeds = <span style="color: black;">&#123;</span><br />
<span style="color: #483d8b;">'latest'</span>: LatestEntries,<br />
<span style="color: #483d8b;">'categories'</span>: LatestEntriesByCategory,<br />
<span style="color: black;">&#125;</span><br />
<br />
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,<br />
<span style="color: #808080; font-style: italic;"># ...</span><br />
<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^feeds/(?P&lt;url&gt;.*)/$'</span>, <span style="color: #483d8b;">'django.contrib.syndication.views.feed'</span>,<br />
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'feed_dict'</span>: feeds<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>,<br />
<span style="color: #808080; font-style: italic;"># ...</span><br />
<span style="color: black;">&#41;</span></div></div>
<p>ici on aura donc deux urls :</p>
<ul>
<li>/feeds/latest</li>
<li>/feeds/categories</li>
</ul>
<p>On peut définir deux templates celui pour justes les titres et celui pour l&#8217;item RSS complet. Les deux templates doivent avoir pour nom :</p>
<ul>
<li>KeyDict_title.html</li>
<li>KeyDict_description.html</li>
</ul>
<p>Soit dans notre exemple :</p>
<ul>
<li>latest_title.html</li>
<li>latest_description.html</li>
<li>categories_title.html</li>
<li>categories_description.html</li>
</ul>
<p>Et tout fonctionne parfaitement dans le meilleur des mondes.</p>
<p>Maintenant prenant un exemple un peu plus compliqué. Imaginons deux apps django, une pour gérer un blog, une pour gérer des reviews de films.<br />
Les deux apps vont donc mettre en place des flux RSS, logique.<br />
Et les deux vont vouloir mettre en place le flux latest. Donc dans chaque répertoire templates des apps, il y aura un sous-répertoire feeds avec les fichiers latest_title.html et latest_description.html</p>
<p>Et là, patatra. Le deuxième flux (dans l&#8217;ordre des INSTALLED_APPS) va utiliser les fichiers templates du premier. Parce qu&#8217;apparement la recherche des templates pour les feeds et transversale.<br />
Donc faut nommer de manière différentes ses flux. latestblogs et latestreviews par exemple.</p>
<p>Et là, miracle, ça fonctionne.</p>
<p>Voilà, c&#8217;est tout.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/04/03/petit-memo-concernant-la-syndication-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Petits tours des méthodes des querysets.</title>
		<link>http://j-mad.com/blog/2010/04/02/petits-tours-des-methodes-des-querysets/</link>
		<comments>http://j-mad.com/blog/2010/04/02/petits-tours-des-methodes-des-querysets/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 09:40:36 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=539</guid>
		<description><![CDATA[
			
				
			
		
Les queryset sont une des composantes importantes de Django. Comment en effet interagir avec la BD sans eux ?
Mais est ce que cet outil si important et si souvent utilisé est si bien connu que ça ?
Parce que tout le monde connait count(), filter(), all() et exclude(). Mais qu&#8217;n est-il des autres méthodes ? Perso, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F02%2Fpetits-tours-des-methodes-des-querysets%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F04%2F02%2Fpetits-tours-des-methodes-des-querysets%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Les queryset sont une des composantes importantes de Django. Comment en effet interagir avec la BD sans eux ?</p>
<p>Mais est ce que cet outil si important et si souvent utilisé est si bien connu que ça ?</p>
<p>Parce que tout le monde connait count(), filter(), all() et exclude(). Mais qu&#8217;n est-il des autres méthodes ? Perso, je suis le premier à aller dans la doc, pour revérifier si ce que je voudrais n&#8217;existe pas déjà&#8230;</p>
<p>C&#8217;est le pourquoi de ce billet, lister quelques méthodes &#8216;à connaître&#8217; des querysets (et puis comme ça la prochaine fois que j&#8217;aurais besoin de vérifier un truc, je pourrais le faire en lisant du français et pas de l&#8217;anglais). (Ce n&#8217;est au final qu&#8217;une redite de la page de doc qui va bien, mais ça peut servir).</p>
<h1>1- Les méthodes qui renvoient un queryset (ou assimilés)</h1>
<h2>annotate(*args, **kwargs)</h2>
<p>une petite méthode bien pratique, qui permet de rajouter des colonnes calculées (en utilisant les classes d&#8217;agrégat Sum,Count, etc défini par django) pour chaque objets récupérés dans le queryset.</p>
<p>Et ça, c&#8217;est plutôt fort. Surtout que l&#8217;on peut, bien entendu, &#8216;traverser&#8217; les foreign key<br />
L&#8217;un des exemples de la doc, montre cela en calculant pour un magasin le prix minimum et maximum des livres en vente :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Store.<span style="color: black;">objects</span>.<span style="color: black;">annotate</span><span style="color: black;">&#40;</span>min_price=Min<span style="color: black;">&#40;</span><span style="color: #483d8b;">'books__price'</span><span style="color: black;">&#41;</span>, max_price=Max<span style="color: black;">&#40;</span><span style="color: #483d8b;">'books__price'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></div>
<h2>values(*fields) et Values_list (*fields)</h2>
<p>Deux méthodes plus que miam.<br />
Values retourne un ValuesQuerySet qui est en fait un queryset composé d&#8217;une liste de dictionnaires au lieu d&#8217;une liste d&#8217;instance d&#8217;objet modèle. Chaque dictionnaire représente un objet, les paire clés / valeur représentant le nom de l&#8217;attribut (la key) et la valeur de l&#8217;attribut (sa valeur).<br />
On peut passer à values un paramètre optionnel *fields, qui permet de spécifier la liste des noms d&#8217;attribut (des strings donc) que l&#8217;on veut récupérer.<br />
Exemple :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span>Blog.<span style="color: black;">objects</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'id'</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">'Beatles Blog'</span>, <span style="color: #483d8b;">'tagline'</span>: <span style="color: #483d8b;">'All the latest Beatles news.'</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span>,<br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Blog.<span style="color: black;">objects</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span>, <span style="color: #483d8b;">'name'</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'id'</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">'Beatles Blog'</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span></div></div>
<p>Deux choses importantes à se rappeler, values ne récupère rien pour les manytomany et dans le cas des FK, la clé du dico est le nom &#8216;vrai&#8217; de l&#8217;attribut dans la table (souvent avec _id donc) et la valeur, la valeur de la PK de la FK. Et comme le voit dans l&#8217;exemple, si on veut passer le nom explicite de l&#8217;attribut de la fk, on peut au choix mettre ou pas le _id, le résultat est le même.</p>
<p>Exemple :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Entry.<span style="color: black;">objects</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'blog_id: 1, '</span>headline<span style="color: #483d8b;">': u'</span>First Entry<span style="color: #483d8b;">', ...}, ...]<br />
<br />
&gt;&gt;&gt; Entry.objects.values('</span>blog<span style="color: #483d8b;">')<br />
[{'</span>blog<span style="color: #483d8b;">': 1}, ...]<br />
<br />
&gt;&gt;&gt; Entry.objects.values('</span>blog_id<span style="color: #483d8b;">')<br />
[{'</span>blog_id<span style="color: #483d8b;">': 1}, ...]</span></div></div>
<p>values_list c&#8217;est à peu près la même chose que values, sauf que c&#8217;est une liste de tuple et pas une liste de dico. On peut en plus lui passer un paramêtre flat que l&#8217;on peut mettre à true , pour &#8216;aplatir&#8217; les tuples quand l&#8217;on demande qu&#8217;un seul champ (juste coolos quand on veut une liste de pk)</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Entry.<span style="color: black;">objects</span>.<span style="color: black;">values_list</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span>.<span style="color: black;">order_by</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>,<span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>,<span style="color: black;">&#41;</span>, ...<span style="color: black;">&#93;</span><br />
<br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Entry.<span style="color: black;">objects</span>.<span style="color: black;">values_list</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span>, flat=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>.<span style="color: black;">order_by</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>, ...<span style="color: black;">&#93;</span></div></div>
<h3>A quoi sert values et values_list ?</h3>
<p>L&#8217;intérêt c&#8217;est qu&#8217;un ValuesQuerySet, c&#8217;est comme un queryset. Et que donc on peut utiliser toutes les méthodes des queryset dessus. Y compris refiltrer, order_by, etc etc ..</p>
<p>Et que dans le même temps, on peut alléger la charge, surtout si on a des gros models dont l&#8217;on ne veut utiliser que quelques champs.</p>
<h2>defer (*fields)</h2>
<p>Permet d&#8217;indiquer au queryset de ne pas récupérer automatiquement le contenu des champs qui sont passés en paramêtre du defer. Ca peut être utile dans le cas de gros champ texte par exemple (imaginons une vue en liste de billet de blog où l&#8217;on ne veut que les titres des billets et pas leur contenu, utiliser un defer(&#8216;body&#8217;) pourrait être une possibilité , utiliser un values en serait une autre)</p>
<p>les champs deferred seront récupérés quand on les appelera explicitement. Pour annuler les defer d&#8217;un queryset, il suffit d&#8217;appeler la fonction avec None en paramêtre.</p>
<h2>only (*fields)</h2>
<p>C&#8217;est l&#8217;inverse du defer, on ne récupère que certains champs.</p>
<h1>2- Les fonctions qui ne renvoient pas un queryset.</h1>
<h2>in_bulk(id_list)</h2>
<p>Cette petite fonction bien sympa prend une liste de pk et renvoie un dico des objets qui correspondent (les clés étant les pk)</p>
<h2>latest(field_name=None)</h2>
<p>Renvoie le dernier objet, inséré dans la base, en se basant sur les dates et en utilisant le champ passé en paramètre (qui doit donc être un champ  date).<br />
Si le model en question définit la Meta get_latest_by, on peut appeler latest sans argument.</p>
<p>Ok, cette fonction &#8216;ne sert à rien&#8217; à part pour rendre plus lisible le code. Mais bon, ça ne mange pas de pain. Et l&#8217;utilisation de la Meta get_latest_by permet de &#8216;centraliser&#8217; la façon de rechercher le dernier, ce qui rendra une modification plus facile.</p>
<h2>aggregate(*args, **kwargs)</h2>
<p>Retourne un dico des valeurs d&#8217;aggrégat calculés non pas objet par objet comme avec annotate, mais sur tout le queryset.</p>
<p>A vous les sommes de champ, les moyennes ou autre. Vive les rapports <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> q = Blog.<span style="color: black;">objects</span>.<span style="color: black;">aggregate</span><span style="color: black;">&#40;</span>Count<span style="color: black;">&#40;</span><span style="color: #483d8b;">'entry'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'entry__count'</span>: <span style="color: #ff4500;">16</span><span style="color: black;">&#125;</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span> q = Blog.<span style="color: black;">objects</span>.<span style="color: black;">aggregate</span><span style="color: black;">&#40;</span>number_of_entries=Count<span style="color: black;">&#40;</span><span style="color: #483d8b;">'entry'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'number_of_entries'</span>: <span style="color: #ff4500;">16</span><span style="color: black;">&#125;</span></div></div>
<p>et comme pour annotate, on peut contrôler le nom, ici de la clé, que notre valeur calculée.</p>
<h2>exists()</h2>
<p>cette fonction n&#8217;existe pas encore dans django, elle sera présente dans la 1.2. Elle permet tout simplement de savoir si le queryset est vide ou pas. (oui je sais, devoir attendre la 1.2 pour avoir cette fonction.. mais bon <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/04/02/petits-tours-des-methodes-des-querysets/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django-rosetta, parce que pierre qui roule n&#8217;amasse pas mousse</title>
		<link>http://j-mad.com/blog/2010/03/28/django-rosetta-parce-que-pierre-qui-roule-namasse-pas-mousse/</link>
		<comments>http://j-mad.com/blog/2010/03/28/django-rosetta-parce-que-pierre-qui-roule-namasse-pas-mousse/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 21:52:44 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[La Django-app du mois]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=502</guid>
		<description><![CDATA[
			
				
			
		
Vous aimez mon titre ? Parce que moi, j&#8217;en suis super fier en fait. Et oui, il m&#8217;en faut peu. Bon donc pour la django-app du mois de février, j&#8217;avais choisi django-transmeta qui permettait de traduire facilement son contenu. Mais un site n&#8217;est pas fait que de contenu, il est aussi fait de label, de [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F03%2F28%2Fdjango-rosetta-parce-que-pierre-qui-roule-namasse-pas-mousse%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F03%2F28%2Fdjango-rosetta-parce-que-pierre-qui-roule-namasse-pas-mousse%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Vous aimez mon titre ? Parce que moi, j&#8217;en suis super fier en fait. Et oui, il m&#8217;en faut peu. Bon donc pour la django-app du mois de février, j&#8217;avais choisi django-transmeta qui permettait de traduire facilement son contenu. Mais un site n&#8217;est pas fait que de contenu, il est aussi fait de label, de menu, de tout plein de truc qu&#8217;il faut internationaliser à coup de .po et de .mo. Ce qui est, il faut bien le dire, un poil chiant. Limite je pourrais dire, qu&#8217;à vouloir traduire tout ces mots, on pourrait bien finir par y laisser notre peau.</p>
<p>C&#8217;est là que django-rosetta intervient.</p>
<h1>1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?</h1>
<p>Comme bien souvent, sur la <a href="http://code.google.com/p/django-rosetta/">page qui lui est destiné, qui est, un google code</a>. Pour l&#8217;installation, rosetta fait dans le rustique : tar.gz ou svn checkout. Brut mais efficace.</p>
<p>Ensuite il suffira de rajouter django-rosetta dans les INSTALLED_APPS  et de rajouter ses urls dans l&#8217;urlpattern qui va bien. Et c&#8217;est tout, après roule ma poule (ou ma pierre, de rosette HA HA).</p>
<p>Pour la doc, la encore, il n&#8217;y a que la page home du google code. Mais l&#8217;app est suffisament bien faite, pour que la doc présente soit amplement suffisante.</p>
<h1>2- Comment ça marche ?</h1>
<p>Django-rosetta vous permet de rendre la rédaction des .po moins chiante que dans un simple gedit. Mais du coup, cela veut dire que l&#8217;application a besoin d&#8217;avoir les permissions d&#8217;écritures sur certains des fichiers de votre arborescence.</p>
<p>Du coup, elle n&#8217;est utilisable que de l&#8217;admin django. C&#8217;est un choix qui me semble, en fait, très logique. Et puis est ce que cela existe des gens qui n&#8217;utilisent pas du tout la partie admin de django ?</p>
<p>Ensuite, c&#8217;est tout simple, on a une liste des fichiers po, avec les pourcentages de traduction effectuées. On en choisit un et on se met au boulot. On peut même choisir si l&#8217;on veut afficher toute s les chaines ou que celle que l&#8217;on n&#8217;a pas encore traduite.</p>
<p>Allez op, deux petites images pour vous montrer le truc, parce que je suis gentil. (Et puis que je ne me suis pas trop fatigué, je reprend honteusement celles du google code officiel).</p>
<p><a href="http://j-mad.com/blog/wp-content/uploads/2010/03/rosetta-1.png" rel="thumbnail"><img class="alignleft size-medium wp-image-504" title="rosetta-1" src="http://j-mad.com/blog/wp-content/uploads/2010/03/rosetta-1-300x146.png" alt="" width="300" height="146" /></a> <a href="http://j-mad.com/blog/wp-content/uploads/2010/03/rosetta-2.1.png" rel="thumbnail"><img class="alignright size-medium wp-image-505" title="rosetta-2.1" src="http://j-mad.com/blog/wp-content/uploads/2010/03/rosetta-2.1-300x228.png" alt="" width="300" height="228" /></a></p>
<p>Voilà, avec cette deuxième app, j&#8217;en ai fini de parler, en tout cas pour un temps, d&#8217;internationalisation. A bientôt (dans un mois) pour de nouvelles découvertes dans le merveilleux pays des app django.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/03/28/django-rosetta-parce-que-pierre-qui-roule-namasse-pas-mousse/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django-transmeta ou comment traduire son contenu sans se faire suer</title>
		<link>http://j-mad.com/blog/2010/02/27/django-transmeta-ou-comment-traduire-son-contenu-sans-se-faire-suer/</link>
		<comments>http://j-mad.com/blog/2010/02/27/django-transmeta-ou-comment-traduire-son-contenu-sans-se-faire-suer/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 17:04:09 +0000</pubDate>
		<dc:creator>J-Mad</dc:creator>
				<category><![CDATA[La Django-app du mois]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://j-mad.com/blog/?p=468</guid>
		<description><![CDATA[
			
				
			
		
Et oui, vous ne rêvez pas, malgré le fait que le mois de février soit ridiculement court, je trouve tout de même le temps d&#8217;écrire mon billet de l&#8217;app django du mois. Comme quoi, tout arrive.
Bon il faut dire, que j&#8217;ai du coup sélectionné une app assez petite, que j&#8217;ai découvert grâce à #django-fr (merci [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F02%2F27%2Fdjango-transmeta-ou-comment-traduire-son-contenu-sans-se-faire-suer%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fj-mad.com%2Fblog%2F2010%2F02%2F27%2Fdjango-transmeta-ou-comment-traduire-son-contenu-sans-se-faire-suer%2F&amp;source=mrjmad&amp;style=normal" height="61" width="50" /><br />
			</a>
		</div>
<p>Et oui, vous ne rêvez pas, malgré le fait que le mois de février soit ridiculement court, je trouve tout de même le temps d&#8217;écrire mon billet de l&#8217;app django du mois. Comme quoi, tout arrive.</p>
<p>Bon il faut dire, que j&#8217;ai du coup sélectionné une app assez petite, que j&#8217;ai découvert grâce à #django-fr (merci les gars) et avec une doc très bien conçu que je vais donc pouvoir honteusement recopier en parti pour vous expliquer comment cela fonctionne.</p>
<h1>1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?</h1>
<p>Sur la page qui lui est dédiée sur google code. Et pour l&#8217;installer, point de tar.gz, de easy_install ou de pip. Le seul moyen de l&#8217;installer consistera à faire un bon vieux svn checkout des familles.</p>
<p>Au niveau de la doc, il n&#8217;y a que la page du project home du google code. Mais par contre, elle est super bien foutue.</p>
<p>Rendre heureux aussi, ceux qui ne parlent pas français (personne n&#8217;est parfait <img src='http://j-mad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p>Django-transmeta tente de répondre à un besoin tout con, comment traduire efficacement son contenu, lorsqu&#8217;on a un site multi langue. Parmi tout les moyens imaginables pour faire cela (j&#8217;en reparlerais en fin de billet), transmeta a choisi de modifier directement les tables des modeles à contenu traduisible.</p>
<h1>2- Comment ça marche ?</h1>
<p>Je vais reprendre, texto, les exemples donnés par la page web de transmeta, parce qu&#8217;ils très clairs. Prenons l&#8217;exemple d&#8217;un model qui décrit un bouquin.</p>
<p>Tel que :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:<br />
title = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span><br />
description = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
body = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span>default=<span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span><br />
price = models.<span style="color: black;">FloatField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>Là, rien n&#8217;est traduisible. Imaginons que l&#8217;on veuille traduire la description et le body. Rien de plus simple, le code du model devient alors :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> Book<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:<br />
<span style="color: #0000cd;">__metaclass__</span> = TransMeta<br />
<br />
title = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span><br />
description = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
body = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span>default=<span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span><br />
price = models.<span style="color: black;">FloatField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> Meta:<br />
translate = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'description'</span>, <span style="color: #483d8b;">'body'</span>, <span style="color: black;">&#41;</span></div></div>
<p>On rajoute une metaclass et on défini dans la classe méta, les champs que l&#8217;on veut traduire.</p>
<p>Il faut ensuite, dans le settings.py, définir les langues que l&#8217;on veut gérer, par exemple :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">LANGUAGES = <span style="color: black;">&#40;</span><br />
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'es'</span>, ugettext<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Español'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,<br />
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'en'</span>, ugettext<span style="color: black;">&#40;</span><span style="color: #483d8b;">'English'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,<br />
<span style="color: black;">&#41;</span></div></div>
<p>Et qu&#8217;est ce que cela fait ?<br />
Un petit manage.py sqlall va vous le dire :</p>
<div class="codecolorer-container python default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE <span style="color: #483d8b;">&quot;fooapp_book&quot;</span> <span style="color: black;">&#40;</span><br />
<span style="color: #483d8b;">&quot;id&quot;</span> serial NOT NULL PRIMARY KEY,<br />
<span style="color: #483d8b;">&quot;title&quot;</span> varchar<span style="color: black;">&#40;</span><span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span> NOT NULL,<br />
<span style="color: #483d8b;">&quot;description_en&quot;</span> text,<br />
<span style="color: #483d8b;">&quot;description_es&quot;</span> text NOT NULL,<br />
<span style="color: #483d8b;">&quot;body_es&quot;</span> text NOT NULL,<br />
<span style="color: #483d8b;">&quot;body_en&quot;</span> text NOT NULL,<br />
<span style="color: #483d8b;">&quot;price&quot;</span> double precision NOT NULL<br />
<span style="color: black;">&#41;</span><br />
<span style="color: #66cc66;">;</span></div></div>
<p>apparaît ici la solution utilisé pour transmeta. Chaque champ qui est défini comme traduisible donne lieu à n champs en bd, pour n langues.</p>
<p>Là vous allez me dire : &#8216;Ok, bien cool, mais comment on fait quand on rajouter une langue ou que l&#8217;on veut faire en sorte qu&#8217;un champ existant qui n&#8217;était pas traduisible le soit ?&#8217;<br />
Forcément, c&#8217;est prévu. Sinon, je n&#8217;aurais pas osé faire de billet. Donc il y des commandes manage.py spécial pour altérer les tables déjà existantes et permettre de rajouter soit des langues, soit des champs traduisibles.<br />
Dernière chose, il y a tout ce qu&#8217;il faut de prévu pour pouvoir gérer ses champs dans l&#8217;admin.</p>
<h4>3- Retour sur la méthode</h4>
<p>Le principe de fonctionnement de transmeta implique de devoir utiliser des alter table à chaque fois que l&#8217;on veut rajouter une langue ou un champ. J&#8217;avoue que je n&#8217;ai jamais aimé les alter table sur du sql. Est ce un tort que j&#8217;ai ? Je ne sais pas.<br />
Vous me direz que si l&#8217;on utilise pas d&#8217;alter table, on se retrouve presque les mains liées et qu&#8217;il ne reste que peu de solution, à part des grosses tables sous la forme &#8216;langue code&#8217;, &#8216;field name&#8217;, &#8216;trad&#8217;. Il est vrai. Mais bon, j&#8217;aime pas les alter table.</p>
<h6>4- Retour sur le titre du billet :</h6>
<p>Tout le monde aura compris, bien entendu, le jeux de mot. C&#8217;est une référence directe à transmeta, l&#8217;entreprise américaine qui faisait des processeurs ni ne chauffaient que très peu et qui donc n&#8217;avait pas besoin de ventilo. D&#8217;où le sans suer. C&#8217;est nul, je sais.</p>
]]></content:encoded>
			<wfw:commentRss>http://j-mad.com/blog/2010/02/27/django-transmeta-ou-comment-traduire-son-contenu-sans-se-faire-suer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
