Fantomas' side - Articles pour le tag djangohttps://blog.fantomas.site/blog/tags/django/Les derniers articles taggés sous djangofrCopyright (c) 2005-2018, Julien FacheSun, 15 Oct 2017 22:18:44 +0000Copier / Paster https://blog.fantomas.site/blog/2017/10/08/copier-paster/ <img src="/media/cache/e9/0b/e90be819ac68de6dc83daa819e60d898.jpg" alt="Copier / Paster" /> <p>De manière professionnelle, j'ai découvert l'utilisation de sites comme <a href="http://pastebin.com">pastebin.com</a> ou encore <a href="http://gist.github.com">gist.github.com</a>. L'idée dernière ces sites nommés communément <strong>Paster</strong>, est de copier/coller un bout de texte ou de code, afin de pouvoir partager cette note de texte facilement en fournissant seulement l'URL de la note aux personnes concernées, c'est surtout pratique dans le cas des messageries instantanées. Les notes étant généralement supprimées au bout d'un certain temps, la question de confidentialité est plus ou moins assurée.</p><p>Voyant la facilité avec laquelle je pouvais sauvegarder et disposer de mes notes, j'ai donc commencé de manière personnelle à utiliser ces sites, mais cette fois-ci en omettant la suppression automatique. À titre d'exemple, j'y enregistre mon carnet d'adresses postales, comme ça j'ai toujours moyen de retrouver une adresse peu importe où je suis du moment que j'ai Internet. </p><p>Jusqu'au moment où je me suis posé trois questions :</p><ul><li>où sont physiquement stockées mes données ?</li><li>sous quel politique légale sont mes données ?</li><li>sont elles vraiment supprimées en cas de demande ?</li></ul><p>Au final cela revient à se demander si je suis le vrai propriétaire de mes données. Je vous laisse imaginer que la réponse à ces questions ne m'a pas toujours satisfait. Globalement dès que le site est hébergé aux USA ou une entreprise américaine fournissant le service, je passe sous leur juridiction donc : DMCA et autres joyeusetés s'appliquent. Je renonce quasiment à tous mes droits, sauf celui à me faire punir pour ce que j'ai pu écrire.</p><p>Bref dans le doute, je me suis dit qu'il ne me coûterait au final pas grand chose de refaire ce genre de site, à titre personnel, tout en personnalisant les fonctionnalités du site comme :</p><ul><li>API</li><li>Versioning</li><li>Expiration automatique</li><li>Coloration syntaxique </li><li>Support de MarkDown et ReStructuredText</li><li>Table des matières</li><li>Téléchargement sous différents formats</li><li>Copier / Coller instantané</li><li>...</li></ul><p>Au final je me retrouve avec une solution personnalisée pour partager des notes, je suis content, mais le problème reste entier pour les autres utilisateur de ce genre de site... </p><p>A l'origine il me semblait qu'Internet est un réseau décentralisé, permettant de résister en cas de coupures d'un ou de plusieurs nœuds qui le composent. </p><p>Mais ces dernières années avec les services proposés sur Internet, est plus en phase de centralisation, c'est-à-dire, un Facebook pour ses amis, un LinkedIn pour son CV, un YouTube pour les vidéos, etc. Laissant peu de place à la concurrence, le tout avec des conditions d'utilisation floues, on risque un jour de frôler une pseudo catastrophe si une de ces entreprises venait à fermer du jour au lendemain. Bref tout le contraire d'Internet...</p><p>Ne voulant pas n'être que pessimiste dans mes propos au sujet d'Internet, je propose cette idée de <em>rendre l'Internet aux gens</em>. Je veux dire par là qu'il n'est pas in-envisageable que les abonnés d'Internet en deviennent les nœuds et non plus les entreprises privées qui se nourrissent de nos contenus tout en imposant leurs conditions.</p><p>Comment ? En France, quasiment tout abonné à Internet possède une "box", permettant d'accéder à divers services, dont le plus connu, la télévision. Il suffirait de fournir à ces box la possibilité d'héberger des sites / services sur mesure. </p><p>Imaginons que vous vouliez vendre des vieilles fringues, au lieu d'aller sur leboncoin.fr, vous mettez l'annonce sur votre box, à charge des moteurs de recherche de référencer l'annonce. Vous voulez prendre des nouvelles de vos amis, vous vous connectez à leur "facebook" personnel. </p><p>Alors, c'est sûr que ça change du fonctionnement actuel d'Internet, ou les gens passent par google pour aller sur facebook (!), que ça pose aussi quelques problèmes au niveau des fonctionnements économiques comme la pub. Mais cela résout aussi celui des données personnelles, de leur collecte. De plus, cette idée à l'avantage que rien n'empêche aux gens de la mettre en place, car Internet n'appartient à personne.</p><p>Le premier FAI français à mettre en place ce genre de micro sites sur sa box, aura pour moi à cœur la satisfaction de ses abonnés, pas seulement leur consommation.</p><p>En attendant, si cela intéresse quelqu'un, sur demande je peux lui fournir le code de mon paster, afin de l'utiliser sur un serveur personnel.</p> fantomas42@gmail.com (fantomas)Sun, 08 Oct 2017 19:36:55 +0000https://blog.fantomas.site/blog/2017/10/08/copier-paster/DéveloppementMigration des blogs de Libération.fr sur Zinnia https://blog.fantomas.site/blog/2014/12/05/migration-des-blogs-de-liberation-sur-zinnia/ <img src="/media/cache/6b/66/6b666c5e70bccdf171c1161326a5ba57.jpg" alt="Migration des blogs de Libération.fr sur Zinnia" /> <p>Depuis maintenant 1 an et demi, en tant que développeur, je travaille pour le site internet <a href="http://www.liberation.fr/">Libération.fr</a>, du journal du même nom.</p><p>Les problématiques sont variées et l'exigence technique au rendez-vous. Grâce à une équipe sympathique et compétente, on a le temps et les moyens de faire de la qualité dans notre travail, le tout dans un environnement particulier, celui d'un quotidien national.</p><p>Il y a quelques semaines, suite à de nombreux échanges et écueils techniques, nous avons décidé de migrer les quelques 350 blogs de Libération hébergés chez <a href="http://www.typepad.com/">Typepad</a>, vers une nouvelle plate-forme qui devra être plus adaptée à nos besoins.</p><p>Étant spécialistes Django nous avons donc décidé d'utiliser <a href="http://www.django-blog-zinnia.com/">Zinnia</a>, la solution de blogs développée par mes soins, afin de bénéficier ainsi de mon expertise dans le domaine et du retour d'expérience des centaines de blogs déjà déployés sur cette solution.</p><p>Une des exigences technique, fut de n'avoir qu'une seule instance Django pour faire tourner toutes les instances de blogs. Car il est inenvisageable pour des raisons de maintenance et de ressources, de devoir installer une nouvelle instance Django à chaque ouverture de blog.</p><p>Zinnia étant modulaire et extensible, l'application a donc servi de socle au projet, puis fût paramétrée et enrichie afin de satisfaire aux besoins d'une plate-forme multi-blogs.</p><p>Donc autour de Zinnia, j'ai développé plusieurs applications aux fonctionnalités spécifiques, dont on peut citer :</p><ul><li>le mécanisme pour rendre Zinnia multi-blogs.</li><li>l'éditeur de contenu, basé sur <a href="http://imperavi.com/redactor/">redactor</a>.&#160;</li><li>le gestionnaire de profils publicitaires.</li><li>l'interface d'administration de la plate-forme.</li><li>le processus de migration de Typepad vers Zinnia.</li><li>et un thème personnalisé aux couleurs de Libération.</li></ul><p>Là où je tire une certaine fierté dans la réalisation de ce projet, c'est qu'à aucun moment je n'ai dû modifier le code source de Zinnia pour satisfaire une exigence ou résoudre un problème, tout cela grâce à la modularité du programme. Chose qui arrive assez rarement dans le monde des applications Django, pour qu'on le souligne.</p><p>Pour finir, grâce à cette réalisation, j'ai aussi pu me prouver que le petit programme de blogs, réalisé à titre personnel pour ce site, a bien évolué. <br />Car désormais il peut tout aussi bien servir de blog personnel très simple, que de plate-forme de blogs hautement personnalisée, chose que je n'avais pas forcément en tête en commençant Zinnia il y a maintenant <a href="http://fantomas.willbreak.it/blog/2008/11/16/changement-adresse-migration-django/">presque 6 ans</a>.</p> fantomas42@gmail.com (fantomas)Fri, 05 Dec 2014 20:20:08 +0000https://blog.fantomas.site/blog/2014/12/05/migration-des-blogs-de-liberation-sur-zinnia/DéveloppementLe temps des releases : django-livereload https://blog.fantomas.site/blog/2014/06/16/le-temps-des-releases-django-livereload/ <img src="/media/cache/0a/47/0a47ce85df248b42aa4ed6d8646b361d.jpg" alt="Le temps des releases : django-livereload" /> <p>Lors de la refonte du site, j'ai découvert l'utilisation de <a title="Gulp" href="http://gulpjs.com/">Gulp</a> et de <a href="http://livereload.com/">LiveReload</a>, qui permettent de se passer de rafraîchir constamment son navigateur lorsqu'on intègre du HTML, CSS ou JavaScript. En effet lorsque une modification est enregistrée sur ces types de fichiers, le navigateur reçoit un signal lui indiquant de recharger soit la ressource, soit l'intégralité de la page.</p><p>Pas mal, mais pas encore assez satisfaisant pour moi, car j'édite aussi principalement des fichiers Python lorsque je développe sous Django, et j'aurais aimé aussi profiter du rechargement automatique du navigateur lorsque que j'édite du code. Malheureusement ce n'était pas aussi simple que cela...</p><p>Sous Django avec le serveur développement, les fichiers Python du projet sont déjà surveillés, et dès qu'une modification est détectée sur ces fichiers, le serveur redémarre pour prendre en compte la modification.</p><p>Initiative louable, mais qui complique grandement la tâche, car si je surveille aussi ces fichiers avec Gulp, le signal de rechargement sera émit et reçu par le navigateur avant que le serveur de développement Django ne soit totalement rechargé et prêt. Résultat, le navigateur n'arrive pas à recharger, je me retrouve avec une page vide et cela devient contre-productif.</p><p>Ce problème à priori peut être résolu au niveau du serveur de développement Django en utilisant des sockets persistantes et à l'heure où j'écris ces lignes un patch est dans l'attente d'intégration : <a href="https://code.djangoproject.com/ticket/18855">https://code.djangoproject.com/ticket/18855</a></p><p>C'est pour toutes ces raisons que j'ai créé et publié <a href="https://pypi.python.org/pypi/django-livereload">django-livereload</a>. Grâce à cette application qui modifie le serveur de développement, vous pouvez désormais profiter du rechargement automatique de la page en cours quand vos fichiers Python sont modifiés.</p><p>Comment ca marche ? Rappelez-vous, le serveur de développement se recharge déjà quand un fichier Python est modifié, et bien quand le serveur est totalement rechargé, une requête de rechargement est émis vers le serveur LiveReload qui lui se chargera de dispatcher la requête vers le navigateur. </p><p>En effet après quelques recherches, j'ai compris que les logiciels comme <a href="http://gulpjs.com/">Gulp</a> ou <a href="http://gruntjs.com/">Grunt</a>, se basaient sur le projet <a href="https://github.com/mklabs/tiny-lr">tiny-lr</a> lorsqu'il fallait utiliser un serveur LiveReload, hors tiny-lr fournis une API en HTTP pour pouvoir contrôler le rechargement des fichiers. Ce qui dans notre cas est l'idéal.</p><p>Pour contribuer, voici l'adresse du projet : <a href="https://github.com/Fantomas42/django-livereload">https://github.com/Fantomas42/django-livereload</a></p> fantomas42@gmail.com (fantomas)Mon, 16 Jun 2014 12:47:53 +0000https://blog.fantomas.site/blog/2014/06/16/le-temps-des-releases-django-livereload/DéveloppementExpériencesMise à jour 2014 du blog https://blog.fantomas.site/blog/2014/04/23/mise-jour-du-blog/ <p>On dit souvent que les cordonniers sont les plus mal chaussés, et en tant que développeur web je confirme l'adage. Ce blog est à l'abandon, depuis pas mal de temps déjà...</p><p>J'ai donc décidé pour remettre le pied à l'étrier, dans un premier temps de le rafraîchir visuellement et de mettre à jours ses composants, afin pourquoi pas le ressusciter dans un second temps.</p><p>Concernant la partie visuelle, j'ai cédé à la mode du design épuré, et ce pour plusieurs raisons. </p><p>L'idée originale étant de mettre en avant le contenu et sa lisibilité, ce genre de thème est adapté en utilisant de bonnes typographies. De plus en me limitant esthétiquement j'ai pu faire quelque chose de maintenable et maîtrisable à mon échelle et intégrer facilement un coté responsive au site qui lui faisait défaut en 2014.</p><p>Lors de cette refonte, je me suis aussi imposé des objectifs chiffrés en terme de temps, histoire de ne pas m'égarer sur des détails et d'avancer rapidement, d'où aussi la simplification esthétique. Cela permet de ne se concentrer que sur le cœur du site, c'est à dire les articles et leur contenu.</p><p>Pour réaliser et intégrer le design j'ai procédé en deux étapes, en réalisant d'abord une charte graphique qui me convenait, puis une fois le rendu satisfaisant à mon goût, j'ai commencé à l'intégrer dans mon système de templates. </p><p>En évitant de mélanger le fond et la forme, c'est à dire d'intégrer le HTML et le CSS en même temps qu'ils soient conçu, j'ai eu l'impression de gagner beaucoup de temps en évitant des errements et des allers-retours inutiles.</p><p>Concernant la partie intégration afin de gagner aussi du temps, j'ai utilisé un combo <a title="Gulp JS" href="http://gulpjs.com/">Gulp</a>, <a title="Sass" href="http://sass-lang.com/">Sass</a>&#160;et <a title="LiveReload" href="http://livereload.com/">Livereload</a>. Dès que je modifie les fichiers Sass, ils sont automatiquement compilés en CSS et dès qu'une modification a lieu dans le CSS ou le HTML, mon navigateur va se rafraîchir automatiquement afin de me la montrer instantanément. Fini l'époque du <em>Ctrl+F5</em> toutes les 15 secondes. :)</p><p>Pour la partie backend, j'ai opéré un nettoyage drastique sur les fonctionnalités inutiles ou presque du site afin d’accélérer au maximum le développement. Je suis resté sur <a title="Django" href="https://www.djangoproject.com/">Django</a>&#160;en utilisant la dernière mouture de <a title="Zinnia" href="http://django-blog-zinnia.com/">Zinnia</a>, mon moteur personnel de blog. La principale différence par rapport à la précédente version du site, vient du fait que les commentaires sont désormais chargés de manière asynchrone en Javascript via <a title="Disqus" href="https://disqus.com/">Disqus</a>. </p><p>Le fait de différer le chargement des commentaires, m'a permis de mettre en cache statique toutes les pages du site, afin de les servir plus rapidement, chose que je ne pouvais faire avant à cause du formulaire de commentaire et la protection <a title="Cross Site Request Forgery" href="http://fr.wikipedia.org/wiki/Cross-Site_Request_Forgery">CSRF</a>.</p><p>Pour finir sur les innovations, en termes de processus, j'ai utilisé la méthode <a title="GIT-flow" href="http://nvie.com/posts/a-successful-git-branching-model/">git-flow</a>, afin de limiter chaque phases de développement dans une branche et de pouvoir déployer le code en production sur une version stable et spécifique. Les outils et le flow proposé par git-flow rendent le processus de développement et de versionning beaucoup plus facile et professionnel, peu importe au final la taille du projet.</p><p>Pour conclure cet article, je dirais que pas mal de chemin a été parcouru depuis le début de ce blog, sous Wordpress, tant sur les domaines de ses aspirations éditoriales et esthétiques que sur le domaine technique. </p><p>Lors du passage à Django, qui m'a mené au développement de Zinnia, je voulais plus de maîtrise sur le code déployé afin de faire des choses plus complexes. </p><p>Maintenant que j'ai fait pleins de choses complexes et plus ou moins utiles, je veux plus de simplicité afin de me concentrer sur l'essentiel. </p><p>Si je dois tirer une certaine fierté de cette refonte, elle viendrait du fait que j'ai réussi à transmettre cet esprit d'essentialité et de simplicité à tous les composants du site, technique ou non.</p> fantomas42@gmail.com (fantomas)Wed, 23 Apr 2014 13:22:09 +0000https://blog.fantomas.site/blog/2014/04/23/mise-jour-du-blog/DéveloppementExpériencesÔ middleware, mon beau middleware : Request Template Loader https://blog.fantomas.site/blog/2011/03/08/o-middleware-mon-beau-middleware-request-template-loader/ <img src="/media/cache/74/59/74593d216dc7558383bf9189981a97cf.jpg" alt="Ô middleware, mon beau middleware : Request Template Loader" /> <p>Dans le monde du web, là où tout est anarchie (ou presque), je me retrouve confronté assez souvent à cette problématique : </p><blockquote><p>Comment afficher le contenu d'un site réalisé avec Django sur un autre site déjà existant ?</p></blockquote><p>Là où je bosse, on aime bien les <a title="Les balises IFRAME" href="http://www.w3.org/TR/html4/present/frames.html#h-16.5">iframes HTML</a> (no comments please :)), mais le contenu ou le style de la frame incluse ne correspondent pas forcément au site recevant la frame. L'idée, vu qu'on se trouve à la base dans un environnement <a title="Le projet Django" href="http://www.djangoproject.com/">Django</a>, serait de déployer un nouveau site, avec son propre jeu de templates prévues pour le site incluant les frames.</p><p>Mais ce genre de technique nécessite de mettre en place un nouveau domaine, de déployer et de maintenir 2 sites. Bon vous me direz que ce n'est pas forcément ce qu'il y a de plus dur, mais il y a moyen de faire mieux. Et surtout que ce passe-t-il si vous devez faire ce genre d'opération non pas sur 1 site, mais sur plusieurs. Tout de suite cela devient plus ennuyeux. :(</p><p>C'est là où intervient la solution du <a title="Les middlewares sous Django" href="http://docs.djangoproject.com/en/dev/topics/http/middleware/">middleware</a>. L'idée est de pouvoir passer en GET un paramètre qui conditionnera le chargement des templates dans le site source. Comme cela peu importe combien de frames au look différent on devra gérer, la mise en forme et la personnalisation du contenu se fera très facilement.</p><p>Maintenant place au code, les explications sur le fonctionnement viennent directement après.</p><pre>import os from urllib import urlencode from urlparse import urlparse from urlparse import urlunparse try: # For Python &lt; 2.6 from urlparse import parse_qs except ImportError: from cgi import parse_qs from django.conf import settings from django.utils.encoding import smart_str from BeautifulSoup import BeautifulSoup GET_VAR_NAME = getattr(settings, 'TEMPLATE_GET_VAR_NAME', 'from_source') class RequestTemplateMiddleware(object): """Middleware to modify on the fly the loading of the templates""" def __init__(self): self.original_template_dirs = settings.TEMPLATE_DIRS def process_request(self, request): source = request.GET.get(GET_VAR_NAME) if source: settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'templates', source),) + \ settings.TEMPLATE_DIRS return None def process_response(self, request, response): settings.TEMPLATE_DIRS = self.original_template_dirs source = request.GET.get(GET_VAR_NAME) if source and '&lt;html' in response.content: soup = BeautifulSoup(smart_str(response.content)) for link in soup.findAll('a'): link['href'] = self.update_link(link['href'], source) for form in soup.findAll('form'): form['action'] = self.update_link(form['action'], source) form.insert(0, '&lt;div&gt;&lt;input type="hidden" name="%s" ' \ 'value="%s" /&gt;&lt;/div&gt;' % (GET_VAR_NAME, source)) response.content = str(soup) return response def update_link(self, link, source): """Update the links with the good GET parameter""" url_parts = urlparse(link) query_dict = parse_qs(url_parts.query) query_dict.update({GET_VAR_NAME: source}) return urlunparse((url_parts.scheme, url_parts.netloc, url_parts.path, url_parts.params, urlencode(query_dict), url_parts.fragment))</pre><p>Comme on peut le voir, ce middleware va court-circuiter l'ordre de chargement des templates en modifiant la variable <strong>TEMPLATE_DIRS</strong> utilisée par <a title="Chargement des templates sous Django" href="http://docs.djangoproject.com/en/1.2/ref/templates/api/#loader-types">django.template.loaders.filesystem.Loader</a>, grâce à la variable <strong>from_source</strong> passée dans l'url en GET. </p><p>Ensuite il ne reste plus qu'à créer le dossier de templates correspondant à la variable <strong>from_source</strong> et d'y placer les templates personnalisés. A savoir que le nom de la variable passée en GET est configurable pour plus de souplesse. </p><p>La seule dépendance requise est <a title="Documentation de BeautifulSoup" href="http://www.crummy.com/software/BeautifulSoup/documentation.html">BeautifulSoup</a> qui va modifier le contenu HTML afin de pouvoir continuer à utiliser le middleware quand on clique sur un lien ou on valide un formulaire.</p><p>Au delà de l'utilité de ce bout de code, j'espère que cela va vous motiver à programmer et utiliser vos propres middlewares, car cela s'avère souvent la meilleure solution à un problème complexe lors du développement d'un site internet avec Django.</p> fantomas42@gmail.com (fantomas)Tue, 08 Mar 2011 14:38:28 +0000https://blog.fantomas.site/blog/2011/03/08/o-middleware-mon-beau-middleware-request-template-loader/DéveloppementExpériencesLe temps des releases : django-blog-zinnia https://blog.fantomas.site/blog/2010/09/16/le-temps-des-releases-django-blog-zinnia/ <img src="/media/cache/2a/46/2a4621e127ec848eb30eb57f5f3f1fdf.jpg" alt="Le temps des releases : django-blog-zinnia" /> <p>Incroyable, après presque 2 ans d'attente, Zinnia l'application Django propulsant ce blog est enfin publiée sur un dépôt public.&#160;</p><p>Le premier article faisant référence à <a title="Première apparition de django-blog-zinnia." href="/blog/2008/11/16/changement-adresse-migration-django/">Zinnia date en effet du 16 Novembre 2008</a>.</p><p>Beaucoup d'évolutions ont été apportées entre cette première version réalisée à titre personnel et celle qui gère le site actuellement. Ceci explique en partie mon manque d'activité sur le site.</p><p>Au final, j'en ai profité pour mettre à jour le code du site en utilisant la version de développement et refondre le skin du site, un peu trop sombre et vieillissant à mon goût.</p><p>Maintenant, concentrons nous sur notre sujet. Tout d'abord <a title="Code source de django-blog-zinnia" href="http://github.com/Fantomas42/django-blog-zinnia">le code source de Zinnia est disponible sur GitHub</a>, ce qui facilite le travail communautaire, donc si vous voulez participer, forker ou télécharger, aucun problème, vous y êtes même encouragé.</p><p>Lors de la publication du code source, je me suis efforcé de documenter un maximum les fonctionnalités ainsi que l'installation, donc pour présenter le projet je vais me baser sur ces documents.</p><p>Tout d'abord, qu'est-ce-que Zinnia ou django-blog-zinnia exactement ?</p><blockquote><p>Zinnia est une application générique pour gérer un blog à travers un site en Django. Elle a été conçue pour publier des articles et le faire efficacement ! De manière générale toutes les fonctionnalités qui peuvent être fournies par une autre application réutilisable écrite en Django ont été mises de coté. Pourquoi réécrire ce qui a déjà été testé et approuvé par les autres ?</p></blockquote><p>Mais plutôt qu'un long discours, je vais dresser la liste actuelle des fonctionnalités disponibles.</p><ul class="simple"><li>Commentaires</li><li>Flux RSS ou Atom</li><li>Vues par archives</li><li>Vues par catégories et tags</li><li>Détection des articles relatifs</li><li><a title="Possibilités du moteur de recherche." href="http://django-blog-zinnia.com/docs/SEARCH_ENGINES.html">Moteur de recherche avancé</a></li><li>Prépublication et expiration</li><li>Widgets</li><li>Sitemaps</li><li>Protection anti-spam avec Akismet</li><li>API <a title="Qu'est ce que MetaWeblog" href="http://en.wikipedia.org/wiki/MetaWeblog">MetaWeblog</a></li><li>Ping dans les annuaires</li><li>Ping des ressources externes</li><li>Support de Bit.ly, Twitter</li><li>Gestion de Gravatar</li><li>Plugin pour <a title="Django-CMS" href="http://www.django-cms.org/">Django-CMS</a></li><li>Travail collaboratif</li><li>Autocomplétion des tags</li><li>Support des Pingbacks et Trackbacks</li><li>WYMeditor ou TinyMCE pour éditer</li><li>Templates génériques prêts l'emploi</li><li>Utilitaire de conversion depuis WordPress</li></ul><p>&#160;Je dois certainement oublier des petites choses, mais ça commence déjà à faire pas mal. D'ailleurs, si vous avez une idée de ce qui pourrait manquer n'hésitez pas à m'en faire part.</p><p>Une documentation complète et mise à jour se trouve à cette adresse : <a title="Documentation de django-blog-zinnia" href="http://django-blog-zinnia.com/docs/">http://django-blog-zinnia.com/docs/</a><br />Vous trouverez dans cette documentation un lien vers une documentation de l'API, ainsi que le <a title="Définition de code coverage." href="http://en.wikipedia.org/wiki/Code_coverage">code coverage</a> des tests effectués sur l'application. Car bien sûr l'application est testée. Ouf !</p><p>J'ai failli oublier de dire qu'une version de démonstration de l'application se trouvait ici : <a title="Démo de django-blog-zinnia." href="http://django-blog-zinnia.com/blog/">http://django-blog-zinnia.com/blog/</a></p><p>Bon il ne reste plus qu'à écrire des articles ! :)</p> fantomas42@gmail.com (fantomas)Thu, 16 Sep 2010 18:51:12 +0000https://blog.fantomas.site/blog/2010/09/16/le-temps-des-releases-django-blog-zinnia/DéveloppementLe temps des releases : Vélib'erator https://blog.fantomas.site/blog/2009/09/24/le-temps-des-releases-veliberator/ <img src="/media/cache/62/ea/62ea6a9ad14f0fac4c578fa52f8b552b.jpg" alt="Le temps des releases : Vélib&#39;erator" /> <p>Suite à mon abonnement à <a title="Vélib" href="http://velib.paris.fr/">Vélib'</a>, habitant près d'une station récemment construite, j'ai vite remarqué que de trouver un vélo en bon état ou une place de parking à proximité avant les 30 minutes fatidiques et payantes pouvait vite devenir un calvaire.</p><p>Sur ce, après quelques recherches,&#160; j'ai pu constater que les informations sur l'état des stations du réseau Vélib' étaient librement accessibles. D'où l'idée de créer un paquet python nommé <a title="Sources du paquet python Veliberator" href="http://pypi.python.org/pypi/veliberator/">Veliberator</a>, me permettant depuis mon shell de consulter l'état de mes stations favorites.</p><p>Pour les fans de la ligne de commande, essayez ceci :</p><pre>$ sudo easy_install veliberator $ sudo synchronize.py $ find_place.py 42008</pre><p>Partant de là, je me dis qu'il serait dommage de m'arrêter à ce stade du développement, d'autant plus que mon problème pour trouver une place libre rapidement ne se résous que depuis mon ordinateur, il faudrait donc que ce service soit accessible partout et pour tout le monde.</p><p>Un site web semble être la solution idéale, d'autant plus si on est capable d'optimiser l'affichage des pages au type de support, par exemple un mobile.</p><p>Equipé de mon module python et de Django, j'ai donc réalisé le site <a title="Vélib'erator la libération des stations Vélib'." href="http://veliberator.com">http://veliberator.com</a>.</p><p>Au programme du site :</p><ul><li>Consultation des <a title="Station Vélib' 42008" href="http://veliberator.com/42008">statuts des stations Vélib'</a>.</li><li>Affichage des stations aux alentours.</li><li>Affichage des <a title="Stations Vélib près de la Tour Eiffel." href="http://veliberator.com/lieux/monument/tour-eiffel/">lieux importants</a> près des stations.</li><li><a title="Flux RSS de la station 12002 et des alentours." href="http://veliberator.com/rss/around/12002">Flux RSS</a> pour monitorer le statut des stations.</li><li>Vues par <a title="Stations Vélib' de Saint Mandé" href="http://veliberator.com/ville/94160/">ville</a>, départements, statut, adresse.</li><li><a title="Statistiques du réseau Vélib'" href="http://veliberator.com/stats/">Statistiques</a> du réseau Vélib'.</li><li>Recherche par : adresse, métro, monument, code postal, coordonnées GPS.</li><li>Calcul des distances.</li><li>Traçage d'<a title="Itinéraire entre la station 42008 et 12001" href="http://veliberator.com/route/42008/12001">itinéraires</a> entre stations Vélib'.</li><li>Gestion de favoris.</li><li>Interfaces claires et unifiées.</li><li>Cartes détaillées et en <a title="Vue plein écran !" href="http://maps.veliberator.com/13053/">plein écran</a>.</li><li>Géo-localisation automatique.</li><li>Internationalisation </li><li>Support pour les téléphones <a title="Vélib'erator version iPhone et mobile." href="http://m.veliberator.com">mobiles et iPhone</a>.</li><li>Support pour les Télésites Freebox.</li></ul><p>En effet le site tourne sous plusieurs versions, chacune adaptées à son environnement d'affichage, et à tout moment je peux consulter ces informations.</p><p>Dans mon cas, quand je rentre du travail en Vélib' et qu'il n'y a plus de place en bas de chez moi, je sais directement où aller pour trouver une place libre, sur mon téléphone. Adieu les rondes au hasard à la recherche d'une place libre... Merci Vélib'erator ! :D</p><p>Si vous avez des suggestions, je suis ouvert à toutes propositions d'amélioration.</p><p><a title="Vélib'erator.com" href="http://veliberator.com">http://veliberator.com</a></p><p><a title="Vélib'erator version mobile" href="http://m.veliberator.com">http://m.veliberator.com</a></p><p><em><strong>Edit 30 septembre 2009</strong> : Suite à un email provenant de la société JCDecaux, je me vois dans l'obligation de ne plus utiliser leurs données sur les stations vélib selon les articles L. 112-3 al 2 et L.341-1 du code de la propriété intellectuelle. Données qui sont pourtant accessible publiquement... A priori, avec Vélib, il vaut mieux éviter les initiatives personnelles.</em></p> fantomas42@gmail.com (fantomas)Thu, 24 Sep 2009 14:16:23 +0000https://blog.fantomas.site/blog/2009/09/24/le-temps-des-releases-veliberator/DécouvertesDéveloppementLe temps des releases : Django-sekh https://blog.fantomas.site/blog/2009/08/31/le-temps-des-releases-django-sekh/ <img src="/media/cache/5a/0b/5a0b1dfc28bb1fa4d28b98d0d50d2208.jpg" alt="Le temps des releases : Django-sekh" /> <p>Vous avez certainement déjà vu dans <strong>Google</strong> quand vous consultez une page depuis son <strong>cache</strong>, les <strong>termes de la recherche sont coloriés</strong> dans le contenu de la page pour permettre de les discerner rapidement.</p><p>De ce principe certains sites ont adapté <strong>la même technique</strong> en coloriant certains mots de la page correspondant à la recherche de l'utilisateur si il provient d'un moteur de recherche.&#160;</p><p>C'est ce que <strong>django-S</strong>earch<strong> E</strong>ngine <strong>K</strong>eywords <strong>H</strong>ighlighter fait ! </p><p>Une fois installé avec <a title="BeautifulSoup" href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a>, il suffit juste d'ajouter ce middleware à la fin de la liste dans votre fichier <strong>settings</strong>.</p><pre>MIDDLEWARE_CLASSES = ( ... 'sekh.middleware.KeywordsHighlightingMiddleware', )</pre><p>Moi quand c'est facile à installer, j'aime ! :D</p><p>Ce middleware va rajouter une balise <strong>span</strong> autour des mots de la recherche, le tout avec des classes qui vont bien permettant la décoration en CSS.</p><p>L'inconvénient est que si votre HTML est mal formatté, le middleware risque de faire planter la page.</p><p>Pour voir <a title="Exemple de django-sekh" href="http://fantomas.willbreak.it/blog/2009/jul/19/release-django-smileys/?hl=django%20middleware">un exemple cliquez ici</a>.</p><p>Pour plus d'informations et pour télécharger le code : </p><p><a title="django-sekh" href="http://github.com/Fantomas42/django-sekh/tree/master">http://github.com/Fantomas42/django-sekh/tree/master</a></p> fantomas42@gmail.com (fantomas)Mon, 31 Aug 2009 18:17:51 +0000https://blog.fantomas.site/blog/2009/08/31/le-temps-des-releases-django-sekh/DéveloppementLe temps des releases : Django-smileys https://blog.fantomas.site/blog/2009/07/19/release-django-smileys/ <p>Parfois il est temps de se sortir les doigts du code, et d'en parler !<br />Mais pour en parler, il faut documenter, ce qui prend un peu de temps, mais j'y travaille.</p><p>Pour commencer je vais vous présenter une de mes applications favorites, par sa simplicité et son utilité incroyable. :D</p><p><strong>Django-smileys</strong> est une application <strong>Django</strong> comme son nom l'indique, permettant d'inclure facilement dans ses templates des smileys, de ce genre :) :p.</p><p>Pour cela, une fois l'application téléchargée et installée dans votre projet django, il vous suffit dans vos templates d'utiliser le filtre qui va convertir tout les code smileys définis dans SMILEYS_LIST.</p><pre>{% load smiley_tags %} {{ object.content|smileys }}</pre><p>Plutôt facile non ? Surtout que l'on peut maintenant convertir tout type de contenu texte.</p><p>La liste des smileys est configurable, ainsi que l'url de dépot et la classe d'habillage CSS.</p><p>Pour télécharger ce projet hallucinant : <a title="Dépot de Django-smileys" href="http://github.com/Fantomas42/django-smileys/tree/master">http://github.com/Fantomas42/django-smileys/tree/master</a></p><p>Bientôt d'autres releases.</p> fantomas42@gmail.com (fantomas)Sun, 19 Jul 2009 13:25:48 +0000https://blog.fantomas.site/blog/2009/07/19/release-django-smileys/DéveloppementPaye ta Fabric ! https://blog.fantomas.site/blog/2009/05/01/paye-ta-fabric/ <img src="/media/cache/19/68/19684b55d03204bbf3823f2bddca5621.jpg" alt="Paye ta Fabric !" /> <p>Le déploiement d'applications, c'est pas toujours facile et rébarbatif surtout quand on travaille sur un parc de machines.</p><p>Imaginons que j'utilise un serveur de version, du genre <em>Subversion</em> ou <em>Mercurial</em> et que j'utilise un ou deux serveurs (test, production 1, production 2, ...) pour héberger mon ou mes applications.</p><p>Le déroulement est le suivant :</p><ul><li>Développement en local. </li><li>Propagation des modifications.</li><li>Connection SSH sur les serveurs.</li><li>Rapatriement les dernières modifications</li><li>On redémarre le soft.</li></ul><p>Vous me direz que cela n'est pas forcément très long, mais quand vous devez le faire souvent et plusieurs fois par jour, on en a vite pleins le dos et cela est <strong>source d'erreur</strong>.</p><p>Heureusement l'informatique étant un sport où celui qui est le plus fainéant gagne, il existe un solution pour se simplifier ces tâches de déploiements à distance.</p><p>Son nom ? <strong>Fabric</strong></p><p>En quelques lignes de Python, définissant des règles, un peu à la manière d'un Makefile, il est possible d'automatiser ce genre d'opération.</p><p>Voici un exemple basique pour le déployement d'un projet Django avec Mercurial :</p><pre>"""Fabric Rules for MyProject"""<br /><br />config.production = ['server.domain.com']<br />config.app_dir = '/home/dev/djangos/myproject'<br /><br />def publish():<br />&#160;&nbsp;&nbsp; """Publish the content by pushing it"""<br />&nbsp;&nbsp;&nbsp; local('hg push')<br /><br />def apache_reload():<br />&nbsp;&nbsp;&nbsp; """Reload the apache process"""<br />&nbsp;&nbsp;&nbsp; sudo('/etc/init.d/apache2 reload')<br /><br />@roles('production')<br />def update():<br />&nbsp;&nbsp;&nbsp; """Update the code source"""<br />&nbsp;&nbsp;&nbsp; run('cd $(app_dir); hg pull; hg update')<br />&nbsp;&nbsp;&nbsp; run('cd $(app_dir); python manage.py syncdb')<br />&nbsp;&nbsp;&nbsp; run('cd $(app_dir); python manage.py loaddata my_dump.json')<br />&nbsp;&nbsp;&nbsp; apache_reload()<br /><br />@roles('production')<br />def debug_on():<br />&nbsp;&nbsp;&nbsp; """Turn debug mode on for the production server."""<br />&nbsp;&nbsp;&nbsp; run("cd $(app_dir); sed -i -e 's/DEBUG = .*/DEBUG = True/' settings.py")<br />&nbsp;&nbsp;&nbsp; apache_reload()<br /><br />@roles('production')<br />def debug_off():<br />&nbsp;&nbsp;&nbsp; """Turn debug mode off for the production server."""<br />&nbsp;&nbsp;&nbsp; run("cd $(app_dir); sed -i -e 's/DEBUG = .*/DEBUG = False/' settings.py")<br />&nbsp;&nbsp;&nbsp; apache_reload()<br /><br />@depends(publish, update)<br />def deploy():<br />&nbsp;&nbsp;&nbsp; """Deploy the website."""<br />&nbsp;&nbsp;&nbsp; pass</pre><p>Un des avantages principaux de <strong>Fabric</strong> est qu'il est possible de l'utiliser sur plusieurs serveurs en même temps, avec des règles spécifiques.</p><p>On lance Fabric, et on peut aller prendre un café. :D<br /> </p><p>Pour information Fabric est basé sur Capistrano, le même principe mais en Ruby.</p><p>Un must, à tester absolument. </p><p><em>Edit </em>: <a title="Fabric" href="http://www.nongnu.org/fab/">le site du projet Fabric</a></p> fantomas42@gmail.com (fantomas)Fri, 01 May 2009 14:53:09 +0000https://blog.fantomas.site/blog/2009/05/01/paye-ta-fabric/DécouvertesDéveloppementStop aux spams sur django.contrib.comments https://blog.fantomas.site/blog/2009/04/16/stop-aux-spams-sur-djangocontribcomments/ <img src="/media/cache/43/84/43846421f58a2c823750cc6f683f6c70.jpg" alt="Stop aux spams sur django.contrib.comments" /> <p>Depuis quelques jours, les formulaires de commentaires fournis par l'application <strong>django.contrib.comments</strong> dans la distribution de Django, sont devenus vulnérables aux spams.</p><p>L'application <strong>comments</strong> contient par défauts plusieurs sécurités pour éviter le spamming, comme un <em>honeypot</em> et la vérification du temps de saisie du commentaires.</p><p>Malgré cela les équipes de spammer sont très réactives, et coder un bot spécifique pour les sites django utilisant ce système de commentaires, rend tous ces sites vulnérables.</p><p>En parallèle de cela, dans la version 1.1b de Django, l'application <strong>comments</strong> acquiert une nouvelle fonctionnalité, qu'est la modération automatique. L'envois de mails en cas de commentaires, et aussi prise en charge.</p><p>J'en ai donc profité pour développer une protection contre le spam plus efficace basée sur <strong>Akismet</strong> à partir de cette nouvelle fonctionnalité.</p><pre>"""Moderator of Entry comments<br />&#160;&nbsp; Based on Akismet for checking spams<br />&nbsp;&nbsp; Need to override the default Moderator,<br />&nbsp;&nbsp; for getting request in parameters."""<br />from django.conf import settings<br />from django.utils.encoding import smart_str<br />from django.contrib.sites.models import Site<br />from django.db.models import signals<br />from django.contrib import comments<br />from django.contrib.comments.signals import comment_will_be_posted<br />from django.contrib.comments.moderation import Moderator<br />from django.contrib.comments.moderation import CommentModerator<br /><br />from django.conf.settings import MAIL_COMMENT<br />from django.conf.settings import AKISMET_COMMENT<br /><br />AKISMET_API_KEY = getattr(settings, 'AKISMET_API_KEY', '')<br /><br />class EntryCommentModerator(CommentModerator):<br />&nbsp;&nbsp;&nbsp; """Moderate the comment of Entry"""<br />&nbsp;&nbsp;&nbsp; email_notification = MAIL_COMMENT<br />&nbsp;&nbsp;&nbsp; enable_field = 'comment_enabled'<br /><br />&nbsp;&nbsp;&nbsp; def email(self, comment, content_object):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if comment.is_public:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(EntryCommentModerator, self).email(comment, content_object)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; def moderate_akismet(self, comment, content_object, request):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; """Need to pass Akismet test"""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not AKISMET_COMMENT:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return False<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from akismet import Akismet<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from akismet import APIKeyError<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; akismet = Akismet(key=AKISMET_API_KEY,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blog_url='http://%s/' % Site.objects.get_current().domain)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if akismet.verify_key():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; akismet_data = {'user_ip': request.META.get('REMOTE_ADDR', ''),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'user_agent': request.META.get('HTTP_USER_AGENT', ''),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'referrer': request.META.get('HTTP_REFERER', 'unknown'),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'permalink': content_object.get_absolute_url(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'comment_type': 'comment',<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'comment_author': comment.userinfo.get('name', ''),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'comment_author_email': comment.userinfo.get('email', ''),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'comment_author_url': comment.userinfo.get('url', '')}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return akismet.comment_check(smart_str(comment.comment),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data=akismet_data,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; build_data=True)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise APIKeyError("Your Akismet API key is invalid.")<br /><br /><br />class EntryModerator(Moderator):<br />&nbsp;&nbsp;&nbsp; """Moderator for Entry"""<br /><br />&nbsp;&nbsp;&nbsp; def connect(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; comment_will_be_posted.connect(self.pre_save_moderation, sender=comments.get_model())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; signals.post_save.connect(self.post_save_moderation, sender=comments.get_model())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><br />&nbsp;&nbsp;&nbsp; def pre_save_moderation(self, sender, comment, request, **kwargs):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; """Overriding the existing method by passing request to allow"""<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(EntryModerator, self).pre_save_moderation(sender, comment, **kwargs)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; moderation_class = self._registry[comment.content_type.model_class()]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if moderation_class.moderate_akismet(comment, comment.content_object, request):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; comment.is_public = False<br /><br /><br /><br />moderator = EntryModerator()</pre><p>Il suffit juste d'installer le module Akismet pour Python, et cela devrais fonctionner en définissant sa clef d'API Akismet.</p><p>Bon par contre, on remarque de suite qu'il est dommage de devoir écrire une nouvelle classe <em>Moderator</em>, pour pouvoir récupérer et passer le context, c'est peu pratique en effet, surtout que <strong>comments</strong> peux le gérer par défaut avec le signal <strong>comment_will_be_posted</strong>.</p><p>Mais à priori cela risque de changer si on en regarde le ticket suivant, prévu pour la version finale de Django 1.1 : <a title="TIcket 10878 sur la modération de commentaires." href="http://code.djangoproject.com/ticket/10878">Ticket 10878, projet Django</a></p><p>Donc une réécriture du code sera certainement nécessaire à la sortie de cette version, qui commence à se faire attendre....</p><p>Pour plus d'informations : <a title="Documentation sur la modération de django.contrib.comments" href="http://docs.djangoproject.com/en/dev/ref/contrib/comments/moderation/">Documentation sur la modération</a></p> fantomas42@gmail.com (fantomas)Wed, 15 Apr 2009 23:14:47 +0000https://blog.fantomas.site/blog/2009/04/16/stop-aux-spams-sur-djangocontribcomments/DéveloppementExpériencesUn CMS en Django ? la suite https://blog.fantomas.site/blog/2009/03/10/un-cms-en-django-la-suite/ <img src="/media/cache/9e/67/9e67f20e07125c3a6db821cb8d28113e.jpg" alt="Un CMS en Django ? la suite" /> <p>Ces derniers temps occupé par certains projets personnels, j'ai pu tester de nouveaux outils de développement. L'idée est d'en faire un retour et je vais commencer par la suite de mon dernier article.</p><p><a href="/blog/2009/jan/25/un-cms-en-django/" title="Un CMS en Django">La dernière fois</a> je vois ai parlé d'une des premières applications disponible en Django permettant d'intégrer un CMS dans son site, nommé <a href="http://django-cms.org" title="Django-cms">Django-cms</a>. Mais mon retour sur cette application m'avait laissé un petit goût de frustration, me laissant penser que ce n'étais pas encore au point. Mais cela va mieux avec <a href="http://code.google.com/p/django-page-cms/" title="Django-page-cms">Django-page-cms</a>. :)</p><p>Ce dernier en plus des fonctionnalités essentielles, comme la gestion de l'arborescence dans le module d'administration et la prise en charge de différents langages, possède certains atouts qui en font mon favoris. </p><p>Voici les petits plus qui m'ont séduit :</p><ul> <li>Définition de plusieures zones de contenus dans un template. (trop fort !)</li><li>Surcharge des urls existante dans le CMS. (enfin !)</li><li>Possibilité d'édition du contenu directement depuis le Front. (la classe !)</li><li>Les contenus du CMS peuvent être interprétés en temps que code. (super !)</li> <li>Pas de besoin de définir une "RootPage" comme dans Django-cms.</li> <li>Gestion des révisions.</li><li>Code propre. </li></ul><p>De plus j'ai pu tester la rapidité de l'équipe du projet qui a intégré en moins de 12h ma contribution pour fixer un bug mineur.</p><p>Un projet qui mérite donc d'être suivis.</p><p>Le site de web de <a href="http://code.google.com/p/django-page-cms/" title="Le site du projet sur GoogleCode">Django-pages-cms</a>.</p><p><em>Edit du 7 avril 2009 :</em> une traduction en français est désormais disponible, ou <a title="Traduction française de django-page-cms" href="http://fantomas.willbreak.it/wp-content/uploads/django-page-cms-fr.po">ici</a>.</p> fantomas42@gmail.com (fantomas)Tue, 10 Mar 2009 16:19:33 +0000https://blog.fantomas.site/blog/2009/03/10/un-cms-en-django-la-suite/DécouvertesExpériencesUn CMS en Django ? https://blog.fantomas.site/blog/2009/01/25/un-cms-en-django/ <img src="/media/cache/7f/35/7f358c9aff2fb8265ac7c39cd2d5fd89.jpg" alt="Un CMS en Django ?" /> <p>Depuis la sortie 1.0 de Django, nombre d'applications plus ou moins complètes ont vu le jour. Mais il manquait encore une application de type CMS qui soit vraiment complète et professionnelle. </p><p>Les fonctionnalités principales d'un CMS seraient de pouvoir créer facilement une arborescence, l'intégration des principaux DublinCore et surtout d'avoir un support pour l'internationalisation notamment au niveau des urls. </p><p> Après plusieurs recherches et tests des différentes applications destinées à ce but, un projet sort du lot. Son nom, Django-CMS, dont la <a href="http://django-cms.org/" title="Django-CMS">page du projet se situe ici</a>. </p><p>Django-CMS avec son interface en Javascript pour organiser les pages en Drag and drop et l'implémentation de toutes les fonctionnalités précèdemment citées font de lui un sérieux concurrent dans le monde des CMS en Django. Je décide donc de le tester et d'en faire ces quelques retours. </p><h1>Points Positifs</h1><p> <strong>Gestion la localisation des URL/IRI</strong>, en effet il est possible d'attribuer une IRI sur une page. Très pratique pour pouvoir gérer du contenu dans plusieurs langues. </p><p><strong>Intégration avec TInyMCE</strong> basé sur le projet <a href="http://code.google.com/p/django-tinymce/" title="Django-TinyMCE">Django-TinyMCE</a> ce qui vous permettra d'ajouter facilement un WYSIWYG à l'édition de vos pages. </p><p><strong>Intégration avec Django-FileBrowser</strong>. <a href="http://code.google.com/p/django-tinymce/" title="Django-Filebrowser">FileBrowser</a> est une application Django qui permet d'envoyer et d'administrer des fichiers depuis l'interface d'administration. Une application très pratique, surtout qu'elle fournit un binding pour l'envoi de fichier avec TinyMCE. </p><p> <strong>L'administration du CMS est classe</strong> et parfaitement bien intégrée dans le module d'administration de Django. La gestion de l'arborescence en Javascript est agréable et bien penser tout comme la gestion des pages. </p><p><strong>Des tags pour faciliter l'intégration</strong>, l'application contient en effet une liste de <em>TemplateTags</em> permettant d'intégrer un breadcrumbs, ou les pages relatives à la navigation. </p><p><strong>Personnalisations des pages</strong>, on peut choisir le template associé à la page et même y passer des <em>Context Processors</em> pour y injecter du contenu personnalisé. Par contre, après les premières joies, je me suis confronté à quelques problèmes. </p><h1>Points Negatifs</h1><p> <strong>Pas ou peu de docs.</strong> La seule documentation disponible se trouve sur le Wiki ou dans le README du paquet. On nous y explique comment installer le projet, mais peu d'explications sur les outils ou le fonctionnement. </p><p><strong>Pas de possibilités de contribuer</strong>, j'ai chercher je n'ai pas trouvé, plutôt frustrant. </p><p> <strong>Pas de réactivités des développeurs</strong>, cela rejoint le point précèdent, même sur l'IRC du projet, on ne peut pas contacter les développeurs. </p><p><strong>Certaines parties du code sont conçues avec les pieds.</strong> Je citerais juste le système de publication dans les différents formats comme le MarkDown ou le ReST, qui est interprété à chaque appel de la page. C'est triste. </p><p><strong>Pas de localisation en français.</strong> Je voulais la fournir mais n'ayant pas la possibilité de contribuer, elle restera aux oubliettes je pense. Mais regardez à la fin de l'article pour la télécharger. </p><p> <strong>L'intégration avec d'autres applications, trop faible.</strong> De mon point de vue, il n'est pas facile d'intégrer Django-CMS directement avec d'autres applications. Ne serait-ce qu'au niveau de la navigation, les outils fournis perdent toutes leur pertinence. </p><p><strong>Pas de notions de pages virtuelles</strong>, pourtant cela résoudrait le problème précèdent. Ces pages pourrais contenir directement l'insertion de modules ou faire une pseudo redirection vers une autre url du site. </p><h1>Conclusions</h1><p> Même si Django-CMS possède beaucoup de qualités, ses points négatifs m'empêchent de penser qu'il peut révolutionner les CMS en Django. Il peut être parfait pour créer un site dédié à l'édition de contenu, mais son architecture et son fonctionnement peuvent l'empêcher de pouvoir se déployer à grande échelle en se faisant intégré avec d'autres applications. </p><p>De plus la réactivités des développeurs est plutôt inquiétante, je n'ai en effet pas pu proposer ma traduction française à l'équipe. Mais une version 2 est dans les cartons. </p><p>Un projet à tester tout de même, pour vous faire votre idée et surtout à surveiller.</p> fantomas42@gmail.com (fantomas)Sun, 25 Jan 2009 20:59:04 +0000https://blog.fantomas.site/blog/2009/01/25/un-cms-en-django/DécouvertesExpériencesChanger son thème d'administration Django https://blog.fantomas.site/blog/2009/01/15/changer-son-theme-dadministration-django/ <img src="/media/cache/20/d3/20d3ddd89d90915c8f0512552e69e0ca.jpg" alt="Changer son thème d&#39;administration Django" /> <p>Je sais pas pour vous, mais l'administration de Django, je peux plus la voir. :)&#160;</p><p>Même si elle reste très jolie est bien pensée, ses teintes bleues me sortent par les yeux, et je voulais en changer. </p><p>Je me suis penché sur la question en me disant qu'il était largement possible d'effectuer un changement, au minimum des teintes. Mais n'étant pas graphiste et estimant la charge de travail à fournir, j'ai abandonné cette idée. </p><p>Mais je suis récemment tombé sur un projet intéressant appelé <a href="http://code.google.com/p/django-grappelli/" title="Django-Grappelli sur GoogleCode">django-grappelli</a>. Le but étant de fournir une alternative aux templates et au style appliqué dans le module d'administration de Django, exactement ce que je recherchais. </p><p> De plus le graphisme m'a tout de suite semblé très clair et soigné, je me suis laissé donc conquérir par ce thème. Quelques <a href="http://code.google.com/p/django-filebrowser/wiki/screenshots" title="Screenshots Grappelli">screenshots ici</a>. Le petit plus de ce projet, c'est le fait de pouvoir facilement insérer ses propres liens en raccourcis dans l'administration. Un must.</p><p> Par contre il existe un gros bémol avec ce thème, son installation. <br />D'après les explications de la documentation, les templates et les médias doivent se substituer à ceux originalement fournis dans la distribution de Django.</p><p> Donc en plus de vous conseiller d'installer ce module, je vais vous détailler comment l'installer de manière moins intrusive et donc plus propre. :) </p><p>Le projet étant composé de 2 dossiers, <em>templates</em> et <em>media</em>, il faut s'arranger pour que Django utilise ces 2 dossiers pour effectuer le rendu de l'administration. </p><h1>Templates</h1><p> La partie la plus facile, est de changer les templates utilisés par l'admin. Dans votre fichier settings, il suffit de rajouter un lien vers les templates du thème dans la section <strong>TEMPLATE_DIRS</strong>. Ce qui va donner la priorité à ces templates. </p><pre>TEMPLATE_DIRS = ( ..., '<em>&lt;chemin vers django-grappelli&gt;</em>/templates/', ) </pre> <h1>Medias</h1><p> Désormais il va falloir changer le comportement de l'acquisition des fichiers statiques dans l'administration. Par défaut le module charge ces fichiers de manière relatives, en ce basant sur la variable <strong>ADMIN_MEDIA_PREFIX</strong>. </p><p>On va changer cela en y mettant une url absolue vers nos médias. </p><pre>ADMIN_MEDIA_PREFIX = 'http://<em>&lt;mondomaine.com&gt;</em>/grappeli/' </pre><p> Ensuite il reste plus qu'a établir un lien sur l'url <strong>/grappelli/</strong> sur le serveur web pour que les nouveaux fichiers comme la css, soient chargés. </p><p>Le tour est joué ! En espérant que ce thème vous plaira et vous motiveras pourquoi pas à faire votre propre thème d'administration pour Django.</p> fantomas42@gmail.com (fantomas)Thu, 15 Jan 2009 19:34:04 +0000https://blog.fantomas.site/blog/2009/01/15/changer-son-theme-dadministration-django/DécouvertesExpériencesIntégrer Twitter dans Django https://blog.fantomas.site/blog/2009/01/06/integrer-twitter-dans-django/ <img src="/media/cache/b4/7d/b47dd9ae960e59e22a6f086587417dec.jpg" alt="Intégrer Twitter dans Django" /> <p>Twitter, c'est le nouveau média à la mode pour lancer le buzz.<br /> Créer en 2006, son but est simple, pouvoir résumer à tout instant, ce que l'on fait, ce que l'on pense, par des messages courts, que l'on envois par SMS. En effet les messages ne doivent pas dépasser 140 caractères. </p><p>De plus votre réseau peut suivre instantanément vos status, enfin bref voilà le <a href="http://fr.wikipedia.org/wiki/Microblog" title="Microblog sur Wikipedia">Micro-Blogging</a> d'inventé. </p><p>Twitter fournis une <a href="http://apiwiki.twitter.com/" title="API Twitter">API</a> pour pouvoir communiquer avec son service. Je me suis alors demandé ce que je pouvais en faire, et ait décidé d'interfacer celle ci avec Django. </p><p> A travers un exemple nous allons voir comment récupérer des informations de Twitter avec les <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#built-in-tag-reference" title="Built-in Templatetags Django">Templatetags</a> Django. </p><p>Première étape, installer l'excellente <a href="http://code.google.com/p/python-twitter/" title="API Python pour Twitter">API python pour Twitter disponible sur GoogleCode</a>. </p><p>Ensuite nous allons créer un module python disponible dans le PYTHON_PATH, que nous appellerons <strong>django-twitter</strong>, et y créer un templatetag qui récupèrera nos derniers status postés. </p><pre>$ mkdir -p django-twitter/templatetags $ cd django-twitter $ touch __init__.py $ cd templatetags $ touch __init__.py $ touch get_tweets.py </pre><p> Ceci va nous créer la structure pour y intégrer notre code. Nous allons maintenant éditer le fichier get_tweets.py et y insérer le code suivant : </p><pre>"""Templates tags for accessing to Twitter""" from django.conf import settings from django.core.cache import cache from django.template import Library, Node from twitter import Api register = Library() class TweetStatusNode(Node): def __init__(self, num, varname): self.num = int(num) self.varname = varname self.key = '%s-%s' % (self.num, self.varname) def render(self, context): tweets = cache.get(self.key) if not tweets: tweets = Api().GetUserTimeline(settings.TWITTER_USER, self.num) cache.set(self.key, tweets, settings.TWITTER_TIMEOUT) if self.num == 1: context[self.varname] = tweets[0] else: context[self.varname] = tweets return '' @register.tag def get_twitter_status(parser, token): """usage : {% get_twitter_status n as tweets %}""" bits = token.split_contents() if len(bits) != 4: raise TemplateSyntaxError, "get_twitter_status tag takes exactly three arguments" if bits[2] != 'as': raise TemplateSyntaxError, "second argument to get_twitter_status tag must be 'as'" return TweetStatusNode(bits[1], bits[3] ) </pre> <h1>Explications</h1><p> La fonction <strong>get_twitter_status</strong> sert de tag et va conditionner les paramètres passés à l'objet Node qui va effectuer la manipulation au sein du template et du context. Si ce code vous semble obscur, je vous conseille d'aller faire un tour sur la <a href="http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags">documentation Django pour les templatetags</a>. </p><p>Comme nous le voyons cette fonction retourne un objet hérité de <strong>Node</strong>, TweetStatusNode. C'est cette objet qui va contenir le code appelant l'API de Twitter. </p><p>De là j'assigne le résultat dans le context du template, et le tour est joué.</p><p> Désormais au sein de mes templates, je peux récupérer mes X derniers status sur Twitter, grâce à ces quelques lignes. </p><pre>{% load get_tweets %} {% get_twitter_status 5 as tweets %} </pre><p> Simple non ? <br /> Une dernière remarque, le système de cache de Django est utilisé, pour limiter les requêtes et le temps d'attente quand on interroge les serveurs de Twitter. </p><p>A partir de là, je pense qu'il est envisageable de faire une application Django complète, qui fournit les mêmes fonctionnalités que le site original, mais l'intérêt reste limité. </p> fantomas42@gmail.com (fantomas)Tue, 06 Jan 2009 16:19:05 +0000https://blog.fantomas.site/blog/2009/01/06/integrer-twitter-dans-django/DéveloppementExpériences