Fantomas’side

Weblog open-source

Archives pour le tag : django

Flux RSS de django

Migration des blogs de Libération.fr sur Zinnia

Depuis maintenant 1 an et demi, en tant que développeur, je travaille pour le site internet Libération.fr, du journal du même nom.

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.

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 Typepad, vers une nouvelle plate-forme qui devra être plus adaptée à nos besoins.

Étant spécialistes Django nous avons donc décidé d'utiliser Zinnia, 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.

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.

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.

Donc autour de Zinnia, j'ai développé plusieurs applications aux fonctionnalités spécifiques, dont on peut citer :

  • le mécanisme pour rendre Zinnia multi-blogs.
  • l'éditeur de contenu, basé sur redactor.  ...

Continuer la lecture

Le temps des releases : django-livereload

Lors de la refonte du site, j'ai découvert l'utilisation de Gulp et de LiveReload, 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.

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...

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.

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.

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 : https://code.djangoproject.com/ticket/18855

C'est pour ...

Continuer la lecture

Mise à jour 2014 du blog

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à...

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.

Concernant la partie visuelle, j'ai cédé à la mode du design épuré, et ce pour plusieurs raisons.

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.

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.

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.

En évitant de mélanger le fond et la forme ...

Continuer la lecture

Ô middleware, mon beau middleware : Request Template Loader

Dans le monde du web, là où tout est anarchie (ou presque), je me retrouve confronté assez souvent à cette problématique :

Comment afficher le contenu d'un site réalisé avec Django sur un autre site déjà existant ?

Là où je bosse, on aime bien les iframes HTML (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 Django, serait de déployer un nouveau site, avec son propre jeu de templates prévues pour le site incluant les frames.

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. :(

C'est là où intervient la solution du middleware. 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.

Maintenant place au code, les explications sur le fonctionnement viennent directement après.

import os
from urllib import urlencode
from ...

Continuer la lecture

Le temps des releases : django-blog-zinnia

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. 

Le premier article faisant référence à Zinnia date en effet du 16 Novembre 2008.

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.

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.

Maintenant, concentrons nous sur notre sujet. Tout d'abord le code source de Zinnia est disponible sur GitHub, 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é.

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.

Tout d'abord, qu'est-ce-que Zinnia ou django-blog-zinnia exactement ?

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 ?

Mais plutôt qu ...

Continuer la lecture

Le temps des releases : Vélib'erator

Suite à mon abonnement à Vélib', 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.

Sur ce, après quelques recherches,  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é Veliberator, me permettant depuis mon shell de consulter l'état de mes stations favorites.

Pour les fans de la ligne de commande, essayez ceci :

$ sudo easy_install veliberator
$ sudo synchronize.py
$ find_place.py 42008

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.

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.

Equipé de mon module python et de Django, j'ai donc réalisé le site http://veliberator.com.

Au programme du site :

Continuer la lecture

Le temps des releases : Django-sekh

Vous avez certainement déjà vu dans Google quand vous consultez une page depuis son cache, les termes de la recherche sont coloriés dans le contenu de la page pour permettre de les discerner rapidement.

De ce principe certains sites ont adapté la même technique en coloriant certains mots de la page correspondant à la recherche de l'utilisateur si il provient d'un moteur de recherche. 

C'est ce que django-Search Engine Keywords Highlighter fait !

Une fois installé avec BeautifulSoup, il suffit juste d'ajouter ce middleware à la fin de la liste dans votre fichier settings.

MIDDLEWARE_CLASSES = (
  ...
  'sekh.middleware.KeywordsHighlightingMiddleware',
)

Moi quand c'est facile à installer, j'aime ! :D

Ce middleware va rajouter une balise span autour des mots de la recherche, le tout avec des classes qui vont bien permettant la décoration en CSS.

L'inconvénient est que si votre HTML est mal formatté, le middleware risque de faire planter la page.

Pour voir un exemple cliquez ici.

Pour plus d'informations et pour télécharger le code :

http://github.com/Fantomas42/django-sekh/tree/master

Le temps des releases : Django-smileys

Parfois il est temps de se sortir les doigts du code, et d'en parler !
Mais pour en parler, il faut documenter, ce qui prend un peu de temps, mais j'y travaille.

Pour commencer je vais vous présenter une de mes applications favorites, par sa simplicité et son utilité incroyable. :D

Django-smileys est une application Django comme son nom l'indique, permettant d'inclure facilement dans ses templates des smileys, de ce genre :):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.

{% load smiley_tags %}

{{ object.content|smileys }}

Plutôt facile non ? Surtout que l'on peut maintenant convertir tout type de contenu texte.

La liste des smileys est configurable, ainsi que l'url de dépot et la classe d'habillage CSS.

Pour télécharger ce projet hallucinant : http://github.com/Fantomas42/django-smileys/tree/master

Bientôt d'autres releases.

Paye ta Fabric !

Le déploiement d'applications, c'est pas toujours facile et rébarbatif surtout quand on travaille sur un parc de machines.

Imaginons que j'utilise un serveur de version, du genre Subversion ou Mercurial et que j'utilise un ou deux serveurs (test, production 1, production 2, ...) pour héberger mon ou mes applications.

Le déroulement est le suivant :

  • Développement en local.
  • Propagation des modifications.
  • Connection SSH sur les serveurs.
  • Rapatriement les dernières modifications
  • On redémarre le soft.

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 source d'erreur.

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.

Son nom ? Fabric

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.

Voici un exemple basique pour le déployement d'un projet Django avec Mercurial :

"""Fabric Rules for MyProject"""

config.production = ['server.domain.com']
config.app_dir = '/home/dev/djangos/myproject'

def publish():
    """Publish the content by pushing it"""
    local('hg push')

def apache_reload():
    """Reload the apache process"""
    sudo('/etc/init.d/apache2 reload')

@roles('production')
def update():
    """Update the code source"""
    run('cd $(app_dir); hg pull; hg update')
    run('cd $(app_dir); python manage.py syncdb')
    run('cd ...

Continuer la lecture

Stop aux spams sur django.contrib.comments

Depuis quelques jours, les formulaires de commentaires fournis par l'application django.contrib.comments dans la distribution de Django, sont devenus vulnérables aux spams.

L'application comments contient par défauts plusieurs sécurités pour éviter le spamming, comme un honeypot et la vérification du temps de saisie du commentaires.

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.

En parallèle de cela, dans la version 1.1b de Django, l'application comments acquiert une nouvelle fonctionnalité, qu'est la modération automatique. L'envois de mails en cas de commentaires, et aussi prise en charge.

J'en ai donc profité pour développer une protection contre le spam plus efficace basée sur Akismet à partir de cette nouvelle fonctionnalité.

"""Moderator of Entry comments
   Based on Akismet for checking spams
   Need to override the default Moderator,
   for getting request in parameters."""
from django.conf import settings
from django.utils.encoding import smart_str
from django.contrib.sites.models import Site
from django.db.models import signals
from django.contrib import comments
from django.contrib.comments.signals import comment_will_be_posted
from django.contrib.comments.moderation import Moderator
from django.contrib.comments.moderation import CommentModerator

from django.conf.settings import MAIL_COMMENT
from django.conf.settings import AKISMET_COMMENT

AKISMET_API_KEY = getattr(settings, 'AKISMET_API_KEY', '')

class EntryCommentModerator(CommentModerator):
    """Moderate the comment of Entry"""
    email_notification = MAIL_COMMENT
    enable_field = 'comment_enabled'

    def email(self, comment, content_object):
        if comment.is_public ...

Continuer la lecture