Django-qsstats, parce qu’en vrai,on adore tous faire des stats.

Ce mois-ci, j’aurais pu écrire plusieurs django-app du mois. Si j’avais eu le temps. Mais bon, le jour où j’aurais le temps, ça se saura. Du coup, alors que l’horloge tourne et qu’il ne me reste plus qu’un jour et demi pour écrire ma django app du mois et mon polargeek, j’ai décidé d’écrire ma django-app du mois pour parler de django-qsstats, une petite application comme je les aime.

C’est à dire, qui ne fait qu’une chose, une toute petite chose, mais qui la fait bien. Et qui du coup est facilement intégrable, sans remord.

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

On la trouve sur sa page github. Il me semble bien que le seul moyen d’installation soit à travers github. Mais bon, cloner un repository git hub, ce n’est pas le plus compliqué.

La doc, elle, se limite au fichier Readme et à la lecture des tests. Mais bon, honnêtement, cela suffit.

Par contre attention, en plus de nécessiter django 1.1 à minimal, cette petite app a besoin de python-dateutil (une petite librairie qui ajoute pas mal d’extension plutôt puissante à datetime, si vous ne connaissez pas, je vous recommande vivement d’aller jeter un oeil (mais pas les deux, après vous ne pourrez plus lire la doc … ) )

2- Mais au fait, à quoi ça sert ?

A presque rien, mais c’est bien utile.:) Lorsqu’on veut faire un minimum de stats, de comparaison ou autre, on se retrouve assez vite à vouloir trouver combien il y a eu de nouveaux articles la semaine dernière, combien d’histoires ont été écrites par des rôlistes durant le mois dernier, ou d’utilisateur enregistré les 6 derniers mois…

Faire cela est très simple, un petit queryset puis des petits filters. C’est très simple, mais bon, c’est rapidement chiant, et puis c’est pas très DRY.

Donc on se retrouve assez vite à faire des petits fonctions pour avoir les dates du mois en cours, ou d’un mois précis..

Où alors on se dit que quelqu’un à surement du le faire à notre place, on cherche un peu et on tombe sur django-qsstats.

3- Comment ça marche ?

C’est vraiment tout simple. Il suffit de mettre l’app dans son python-path. Ensuite un peu l’utiliser. Rien à faire de plus. Même pas de syncb vu que c’est une app sans model. (il y a un fichier models mais il n’est là que pour les tests).
Ensuite, ben un exemple sera plus parlant (je reprend l’exemple du site officiel)  :

from django.contrib.auth import User
import qsstats

qs = User.objects.all()
qss = qsstats.QuerySetStats(qs, 'date_joined')

print '%s new accounts today.' % qss.this_day()
print '%s new accounts this month.' % qss.this_month()
print '%s new accounts this year.' % qss.this_year()
print '%s new accounts until now.' % qss.until_now()

Vous le voyez, c’est assez facile. On construit son queryset et ensuite on le passe à qsstats en lui indiquant le champ date qui devra servir au filtrage.

Déjà là, ça serait pas mal. Mais il y a mieux. Il existe la fonction time_series qui permet de récupérer une liste de valeur. Par exemple :

from django.contrib.auth import User
import datetime, qsstats

qs = User.objects.all()
qss = qsstats.QuerySetStats(qs, 'date_joined')

today = datetime.date.today()
seven_days_ago = today - datetime.timedelta(days=7)

time_series = qss.time_series(seven_days_ago, today)
print 'New users in the last 7 days: %s' % [t[1] for t in time_series]

qui donnera :
New users in the last 7 days: [3, 10, 7, 4, 12, 9, 11]

Si cela itère par jour, ce n’est pas magique, c’est parce jour (enfin day) est l’argument step par défaut. Mais on peu bien entendu changer la taille du pas.

Enfin, par défaut, toutes les fonctions utilise Count pour calculer les résultat. (et quand je dis Count, c’est effectivement la class Count des Aggregat de django) Mais on peut changer ce comportement en donnant une valeur au paramètre agregate_class du QuerySetStats.

4-Conclusion

Comme je le disais en introduction, j’aime beaucoup les petites apps qui font des petits trucs, mais qui le font bien. C’est bien souvent plus utile que les grosses apps qui font tout et le café et qui sont bien plus difficile à intégrer (ceci n’est pas une critique de pinax hein, ne me faite pas dire ce que je n’ai pas dit).

Donc j’aime forcément, beaucoup qsstats.

Une petite information un fork de qsstats a été créé, sur bitbucket (et que vous trouverez sur pypi). Il s’appelle django-qsstats-magic. Il rajoute la gestion des heures et des minutes, une optimisation qui fonctionne avec mysql et modifie des trucs en interne. Mais effectivement, je n’ai pas poussé plus loin mes investigations.

Django-taggit, le tag est mort, vive le tag ..

J’ai déjà fait, il y en fait 11 mois, un billet de la django app du mois sur une app de tag, django-tagging. Lorsque je l’ai testé, django-tagging était à la version 0.3. Aujourd’hui, elle est version 0.3.1. Et les derniers commit remonte à janvier 2010 ( ce sont ceux ayant aboutis à la version 0.3.1)

Je me suis donc dit, qu’il était peut-être tant de revenir sur le sujet et de présenter une autre app django, sur le même sujet, qui même si pour l’instant présente quelques lacunes comparée à django-tagging, me semble prometteuse.

Et cette app, c’est, roulement de tambour…., django-taggit d’Alex Gaynor (un trublion bien connu pour ceux qui font du django)

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Alors on le trouve tout simplement sur sa page Pypi ou sur sa page github d’ailleurs

Pour l’installation rien de plus simple :

  • un easy_install ou un pip
  • un git clone

Pour la doc, là il n’y a vraiment rien à redire, le projet offre une doc très bien fournie sur readthedocs.org.

2- Mais au fait, à quoi ça sert ?

Tout simplement à taguer des objets. Exactement comme django-tagging donc. Vous allez pouvoir taguer vos objets, filtrer les objets en fonction des tags qu’ils ont ou trouver des objets similaires de par leur tag.

Vous allez aussi pouvoir modifier légèrement la mécanique interne. Par exemple si utiliser des generics key ne vous plait pas, tout est prévu pour que vous puissiez simplement les remplacer par des foreign key. Vous pourrez aussi changer d’autre mécanismes comme le model utilisé pour sauver les Tags.

3- Comment ça marche ?

Tout d’abord il faudra que vous ajoutiez, pour chaque models que vous voulez rendre ‘tagable’ un manager de tag. (Pour ceux qui se souviennent django-tagging permet de taguer directement des instances de models, sans modifier la classe Model en question).

Ca peut paraître un peu lourd et ça rend l’app assz intrusive, mais bon, c’est comme ça. Et puis du coup ça permet, il faut bien l’avouer d’avoir une écriture plus fluide et plus ramassé de son code. Nul besoin de toujours passer par la classe Tag en filtrant sur l’objet dont l’on veut récupérer les tags. Un simple object.tags suffit pour avoir tout ses tags.

Facilité d’utilisation ou intrusivité, à vous de choisir, django-taggit, lui  à choisit. (Et bon, au pire, un bon petit contribute_to_model devrait permettre une extensibilité moins intrusive).

Pour ajouter les tags, les syntaxes possible sont à peu près les mêmes que celle de django-tagging, à savoir (l’image est une capture d’écran d’une partie de la doc) :

Un truc à ne pas oublier, django-taggit utilise des many to many. Donc, n’oubliez pas le save_m2m si vous utilisez des forms.

Ensuite, vous pourrez bien entendu supprimer des tags, les lister, filtrer des objets en fonction de leur tags ou avoir une liste des objets similaires. C’est une vrai liste qui est classée par ordre de similarités.

4- Une app peut en cacher deux autres.

Là, à cette instant de votre lecture vous vous dites peut-être ‘Mais mer..mince alors, il manque des trucs comparés à django-tagging, il n’y a même pas de templates tags d’affichage’.

Et vous auriez raison. Sauf que, sauf que… Il y a des applications qui étendent django-taggit à savoir :

5- Au final

Vu le statut de quasi moribond de django-tagging comparé à la vigueur actuelle de django-taggit, je pense vraiment que si vous avez besoin d’une application qui gére les tags, django-taggit est un meilleur choix. Et puis, je trouve ça rassurant qu’il y ait des applications externes pour étendre django-taggit.

Django Simple Captcha et tout devient si simple

Comme d’habitude le mois d’aout fut une vraie folie. Et qui dit mois de folie dit, billet qui prennent du retard. Heureusement que j’ai pu tricher en publiant la première interview. (ben oui c’est beaucoup plus rapide de poser des questions que d’y répondre, enfin beaucoup plus rapide d’écrire les questions dans un mails quoi).

Du coup, je suis presque en retard pour la django app du mois. Et pour ne pas être en retard, j’ai choisi pour ce mois ci, une django app simple, mais très utile, django simple captcha (pour la petite histoire j’ai découverte cette app en testant django-tellafriend, une application dont il faudra que je vous parle également).

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Alors on le trouve, tout simplement, sur la page google code qui lui est consacré. Pour l’installation,   c’est comme toujours du classique (ha ce que j’aimerais un jour, avoir une surprise à ce niveau là, pouvoir gouter à un peu de nouveauté… mais non, c’est toujours pareil.

Vous avez donc le choix entre :

  • easy_install
  • un tar.gz de la dernière release
  • un checkout de SVN

Dans tout les cas, il vous suffira une fois votre petite application installée, de la rajouter dans les INSTALLED_APP, de lancer un petit syncdb et magie… ça fonctionnera.

Enfin, si vous avez pensé à installer PIL, bien entendu.

La doc elle, est minimaliste mais plutôt claire et bien faite.

2- Mais au fait, à quoi ça sert ?

He ben mon cher ami, c’est indiqué dans le titre. C’est une application de captcha. Elle permet dans sa version de base de proposer trois méthodes de tests de l’utilisateur :
le très classique lettre dans le désordre
l’opération mathématique (toi aussi répond à 4+2)
le choix d’un mot, au hasard, dans un dictionnaire.

Et là, ou c’est vraiment le top avec cette petite app, c’est que si vous avez installé Flite, vous pourrez même avoir votre captcha en Text-so-speech, et vive l’accessibilité !!

3- Comment ça marche ?

En fait rien de plus simple, l’app fourni tout simplement un noueau type de Field a utiliser dans un formulaire.

Et oui, rien de plus simple.

On crée son formulaire, on rajouter un champ Captcha et quand le formulaire a été posté, on fait un joli is_valid() pour savoir si c’est bon.
Et au niveau de la configuration, les possibilités sont très complètes. On peut configurer le taux de bruit appliqué à l’image, les inclinaisons maximums appliqués aux lettres et aux chiffres, la font à utiliser ainsi que sa taille, les différentes couleurs, etc etc,

4- Mais encore

Ce qui est de bien avec cette app, c’est qu’en plus de penser à tout ce qui accessibilité, elle est bien pensé. Elle vous permet en effet de rajouter vos propres générateurs de tests. Il suffit de coder une petite fonction qui renverra un tuple contenant la question et sa réponse dans un tuple. Et le tour est joué.

Et ça c’est plutôt très sympa.

Dernière précision, la page google code contient un bouton flattr, si vous avez un compte flattr (cet excellent nouveau système de rétribution dont il faudra que je parle un jour, mais google est votre ami), n’hésitez pas à cliquer sur le bouton.

Django-websocket parce que sans chaussettes, le web, il pue un peu des pieds

Et oui, malgré la chaleur, malgré les vacances, la plage et l’appel de starcraft 2, malgré tout cela, je reste fidèle au poste et je publie une django app du mois. Bon ok, c’est le dernier jour du mois, mais je suis encore dans les clous.

Mais par contre, vu que c’est l’été, les vacances, je vais pour une fois parler d’une app qui est pour faire tout sauf de la prod. C’est une app toute jeune et qui en plus s’aventure dans un domaine encore très peu supportés dans les navigateurs (pour l’instant uniquement dans Chrome 4, Firefox 4 et Safari 5) , celui des websockets. C’est quoi une websocket vous allez me dire ? C’est un mécanisme qui apparaît dans HTML 5 et qui permet d’avoir un mécanisme de connexion persistante et bi directionnelle entre le serveur web et le browser de l’utilisateur. Trop cool vous allez me dire. Je ne puis qu’être d’accord avec vous. (pour plus d’infos sur les websockets vous pouvez aller lire la page wikipedia ou la norme W3C qui est plutôt facile à lire).

Django-websocket est donc une toute récente app (version 0,3 à l’heure ou j’écris ce billet) qui permet de commencer à s’amuser avec ces adorables websockets.

1- Où on le trouve, comment on l’installe, la doc.

Vous trouverez django-websocket sur sa page pypi ou sur sa page github. L’installation se fera donc soit :

  • avec easy_install
  • un git clone

Comme le code évolue pas mal et que de toute façon c’est pour l’instant plus une app pour tester et pas pour mettre en prod, moi, je vous conseillerais le git clone qui vous permettra d’avoir plus souvent une app à jour.

La documentation est plutôt bien fournie, claire et suffit pour démarrer. Le repository github permet d’avoir en plus les tests et une petite application example de echo.

2- Comment ça marche ?

En fait c’est vraiment super facile, il suffit d’utiliser deux décorateurs de vues soit :

  • require_websocket pour obliger la vue à fonctionner en websocket
  • accept_websocket si l’on veut permettre à la vue de fonctionner sans les websockets.

Ensuite il n’y a qu’un seul objet à utiliser request.websocket sur lequelle on pourra :

  • faire des attentes et récupérer un message quand il y en a un (wait)
  • vérifier si il y a des messages ( has_messages )
  • lire un message ( read )
  • envoyer un message ( send )
  • les utiliser comme un iterator (ce qui ferrait comme un wait dans une boucle avec la gestion en plus de la fermeture de la socket )

Petite précision, le serveur de développement de django n’est pas multithread, il n’est donc pas possible d’ouvrir deux requêtes concurrentes avec. L’app fourni donc une commande spéciale pour le runserver ( –multithreaded ) qui permet de contourner le problème.

3- Un petit Mad Exemple

Histoire de m’amuser un peu avec l’app, j’ai commis un petit exemple avec, en me basant sur le echo exemple. Mon exemple est tout con, vous entrez une chaine de caractère et je lance (grâce à restkit) une recherche google toute les 30 secondes sur la chaine de caractère. Les dix premiers résultats de la recherche sont ensuite affichés grâce à la websocket.

Vous pourrez trouver le code en question sur le tout nouveau repository bitbucket que j’ai du coup, crée pour l’occasion.

Django-improved-inlines, enrichissez facilement vos contenus et ça, sans payer l’ISF

La pluie ayant décidé d’être l’invité surprise du week-end, j’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’application django du mois, j’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’où le improved) qui fait elle même parti du package django-basic-apps. Oui je sais, ça commence à faire un arbre généalogique digne d’une série américaine (ou du trône de fer).

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Vous le trouverez sur sa page github. C’est d’ailleurs là que vous pourrez apprendre que cette sympathique petite app est une version modifiée de l’app inlines de django-basic-apps.

Pour l’installation deux méthodes :
directement en clonant le repository git de github
avec un petit easy_install bien de chez nous.

Attention, l’application pour fonctionner à besoin de BeautifulSoup mais l’installation par easy_install ne vous l’installera pas automatiquement. Un petit easy_install beautifulsoup sera donc de rigueur. Et oui.

Quand à la doc, elle tient dans un mouchoir de poche, à savoir le fichier readme mais au vu de la simplicité de l’app, ce n’est pas vraiment dérangeant.

2- Mais au fait, à quoi ça sert ?

En fait c’est tout simple. Cela vous permet, lorsque vous rédigez des contenus, d’insérer à l’intérieur d’autre contenu gérer par votre django. Et en les mettant en forme avec des templates spécifiques.

Imaginons par exemple que vous voulez insérez des images d’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’est pas de la magie.

3- Comment ça marche ?

En fait, cela marche en deux temps. Tout d’abord dans le template d’affichage de votre contenu principal, il faut déclarer et utiliser le template de django-improved-inlines, comme ceci :

{% load inlines %}
…....
{{ post.body|render_inlines }}

Ensuite, tout va se jouer dans votre contenu, ici le body de votre post. Vous allez parsemer celui si de bouts d’xml qui seront process par BeautifulSoup et Improved-Inlines et qui seront transformés en html (grâce à un template).

L’exemple le plus simple est :

<inline type="media.photo" id="1" />

qui affichera l’objet de pk 1 qui est modélisé par la classe photo contenu dans l’app media.

Mais vous pourrez également utiliser les attributs xml suivant :
ids pour afficher plusieurs id, séparées par des virgules.
filter pour passer un filtre django
template pour choisir le template django qui sera utilisé (par défault l’app utilise inlines/app_model.html)
class qui permet de passer une class au template

ce qui donnerait :

<inline type="calendar.event" filter="date__gte=datetime.date.today()" template="calendar/event_inline.html" />

ou encore :

<inline type="app.model" id="<some pk>"/> <inline type="app.model" ids="<some pk>,<some other pk>" />

4-Conclusion

Je n’ai pas encore eu l’occasion de m’amuser, ‘pour de vrai’ avec cette appli toute simple, ce n’est pas l’envie qui m’en manque parce que je pense lui trouver une foule d’application qui me faciliteront grandement la vie.
J’ai une seule petite appréhension que le process par BeautifulSoup ne ralentisse pas quelque peu le rendering des pages. Ca serait d’ailleurs un ralentissement à évaluer. En tout cas, amusez vous bien avec cette appli aussi simple, qu’utile.

Django-samaritan, parce que tout le monde a le droit d’aimer Bruce Willis

Le mois de mai est toujours un mois compliqué. Normalement c’est à cause de tout ces jours fériés qui sont autant d’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’ai de temps pour rien… A croire que c’est le mois de mai lui-même qui a pour conséquence que l’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’application du mois que j’ai choisi est une toute petite application, que je n’ai en fait pas eu l’occasion d’essayer ‘en vrai’. (et puis bon, je n’allais pas cracher sur la possibilité de faire un jeu de mot coolos en parlant d’un film que j’adore …)

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

On le trouve sur la page github qui va bien et c’est tout. Quand à la doc, elle est, elle aussi uniquement sur le github

La doc se découpe d’ailleurs entre :

  • le Readme
  • le Install
  • les commentaires dans le code.

C’est peu vous aller me dire, mais vu que l’app fait, en tout et pour tout, moins de 200 lignes, c’est suffisant.

2- A quoi ca sert ?

A remplacer le model django.contrib.auth.models.User par un des siens, d’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.

3- Comment ça marche ?

Il y a deux façons possibles de le faire marcher.

En l’installant puis en l’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’ailleurs). Et on utilise les spécialisations des FK,OtO et M2M.

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’auteur de l’app lui même.

3- Retour ?

Et oui, je sais, c’est un comble. Mais bon, c’est mes billets, alors je fais ce que je veux. Donc, si l’un de vous a des retours sur l’utilisation de cette app, je suis bien entendu preneur, ne vous gênez surtout pas.

Django-request , ne partez plus en quest de vos stats

Et non, vous ne rêvez pas, on est même pas le 15 avril et déjà, déjà, le billet de l’app django du mois est là. Mais bon, les rencontres django ayant lieu dans maintenant 14 jours et n’ayant pas encore commencer à préparer ma conf, même pas le premier mot (enfin si, bonjour), ce qui fait que je suis ‘dans la banade’, comme l’a fait si justement remarquer il y a peu @daks_

Donc, je préfère me ‘débarrasser’ tout de suite de l’app du mois, comme ça, ça sera au moins une chose de faite.

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.

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

On le trouve à deux endroits :

A noter que quasiment toute la doc se trouve être sur la partie dédiée à django-request sur le site de son auteur.

Pour l’installation, facile, un git clone, un téléchargement de source ou alors pip et easy_install.

Quand à la doc, elle est vraiment très fournie et complète, permettant d’installer, de configurer, d’utiliser, la totale quoi.

2- A quoi ca sert ?

Ben à faire des stats, je l’ai déjà dit. Qui ne seront visibles que dans la partie admin.

On peut avoir de jolis graphiques concernant :

  • les visiteurs uniques
  • les visites basées sur des referrer différents
  • les requêtes reçues par le serveur
  • les requêtes venant des moteur de recherches
  • les requêtes provenant du javascript
  • les requêtes en SSL
  • les requêtes faites par un utilisateur
  • le nombre d’erreur 404
  • le nombre d’erreur, toutes erreurs comprises
  • le nombre d’utilisateur enregistré sur le site qui ont fait des requêtes

Par défaut les calculs seront fait pour les visiteurs uniques, les visites en fonctions des referrers et le nombre global de requêtes.

On obtient ensuite un joli petit graphique qui nous donne tout plein d’infos. Et plein de petits tableaux pour en avoir encore plus.

Et on peut même avoir, des petits templates tags pour voir les users actifs sur le site

3- Comment ça marche ?

Il suffit d’ajouter ‘request’ dans ses installed_apps et d’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’est bien expliqué dans la doc).

Ensuite, tout ce passe dans l’interface d’admin

4- Tips de chez Jmad.

Quand j’ai installé le tout avec easy_install, j’ai oublié de rajouter les chemins pour avoir les templates admins de l’app. Résultat je n’avais rien dans l’admin. Faites y attention ou alors installez request directement dans votre projet django, comme une de vos apps.

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 ‘machin qui a été truncated’. J’ai passé la taille du champ à 200 pour être tranquille.

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’auteur par exemple). N’oubliez pas de changer cette option si cela vous dérange.

C’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’admin, vous cliquez sur la ligne Request de l’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.

Django-rosetta, parce que pierre qui roule n’amasse pas mousse

Vous aimez mon titre ? Parce que moi, j’en suis super fier en fait. Et oui, il m’en faut peu. Bon donc pour la django-app du mois de février, j’avais choisi django-transmeta qui permettait de traduire facilement son contenu. Mais un site n’est pas fait que de contenu, il est aussi fait de label, de menu, de tout plein de truc qu’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’à vouloir traduire tout ces mots, on pourrait bien finir par y laisser notre peau.

C’est là que django-rosetta intervient.

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Comme bien souvent, sur la page qui lui est destiné, qui est, un google code. Pour l’installation, rosetta fait dans le rustique : tar.gz ou svn checkout. Brut mais efficace.

Ensuite il suffira de rajouter django-rosetta dans les INSTALLED_APPS  et de rajouter ses urls dans l’urlpattern qui va bien. Et c’est tout, après roule ma poule (ou ma pierre, de rosette HA HA).

Pour la doc, la encore, il n’y a que la page home du google code. Mais l’app est suffisament bien faite, pour que la doc présente soit amplement suffisante.

2- Comment ça marche ?

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’application a besoin d’avoir les permissions d’écritures sur certains des fichiers de votre arborescence.

Du coup, elle n’est utilisable que de l’admin django. C’est un choix qui me semble, en fait, très logique. Et puis est ce que cela existe des gens qui n’utilisent pas du tout la partie admin de django ?

Ensuite, c’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’on veut afficher toute s les chaines ou que celle que l’on n’a pas encore traduite.

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

Voilà, avec cette deuxième app, j’en ai fini de parler, en tout cas pour un temps, d’internationalisation. A bientôt (dans un mois) pour de nouvelles découvertes dans le merveilleux pays des app django.

Django-transmeta ou comment traduire son contenu sans se faire suer

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’écrire mon billet de l’app django du mois. Comme quoi, tout arrive.

Bon il faut dire, que j’ai du coup sélectionné une app assez petite, que j’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.

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Sur la page qui lui est dédiée sur google code. Et pour l’installer, point de tar.gz, de easy_install ou de pip. Le seul moyen de l’installer consistera à faire un bon vieux svn checkout des familles.

Au niveau de la doc, il n’y a que la page du project home du google code. Mais par contre, elle est super bien foutue.

Rendre heureux aussi, ceux qui ne parlent pas français (personne n’est parfait 🙂 ).

Django-transmeta tente de répondre à un besoin tout con, comment traduire efficacement son contenu, lorsqu’on a un site multi langue. Parmi tout les moyens imaginables pour faire cela (j’en reparlerais en fin de billet), transmeta a choisi de modifier directement les tables des modeles à contenu traduisible.

2- Comment ça marche ?

Je vais reprendre, texto, les exemples donnés par la page web de transmeta, parce qu’ils très clairs. Prenons l’exemple d’un model qui décrit un bouquin.

Tel que :

class Book(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
body = models.TextField(default='')
price = models.FloatField()

Là, rien n’est traduisible. Imaginons que l’on veuille traduire la description et le body. Rien de plus simple, le code du model devient alors :

class Book(models.Model):
__metaclass__ = TransMeta

title = models.CharField(max_length=200)
description = models.TextField()
body = models.TextField(default='')
price = models.FloatField()

class Meta:
translate = ('description', 'body', )

On rajoute une metaclass et on défini dans la classe méta, les champs que l’on veut traduire.

Il faut ensuite, dans le settings.py, définir les langues que l’on veut gérer, par exemple :

LANGUAGES = (
('es', ugettext('Español')),
('en', ugettext('English')),
)

Et qu’est ce que cela fait ?
Un petit manage.py sqlall va vous le dire :

CREATE TABLE "fooapp_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"description_en" text,
"description_es" text NOT NULL,
"body_es" text NOT NULL,
"body_en" text NOT NULL,
"price" double precision NOT NULL
)
;

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.

Là vous allez me dire : ‘Ok, bien cool, mais comment on fait quand on rajouter une langue ou que l’on veut faire en sorte qu’un champ existant qui n’était pas traduisible le soit ?’
Forcément, c’est prévu. Sinon, je n’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.
Dernière chose, il y a tout ce qu’il faut de prévu pour pouvoir gérer ses champs dans l’admin.

3- Retour sur la méthode

Le principe de fonctionnement de transmeta implique de devoir utiliser des alter table à chaque fois que l’on veut rajouter une langue ou un champ. J’avoue que je n’ai jamais aimé les alter table sur du sql. Est ce un tort que j’ai ? Je ne sais pas.
Vous me direz que si l’on utilise pas d’alter table, on se retrouve presque les mains liées et qu’il ne reste que peu de solution, à part des grosses tables sous la forme ‘langue code’, ‘field name’, ‘trad’. Il est vrai. Mais bon, j’aime pas les alter table.

4- Retour sur le titre du billet :

Tout le monde aura compris, bien entendu, le jeux de mot. C’est une référence directe à transmeta, l’entreprise américaine qui faisait des processeurs ni ne chauffaient que très peu et qui donc n’avait pas besoin de ventilo. D’où le sans suer. C’est nul, je sais.

Tagcon, où comment écrire simplement les templatetags, cong !!

Oui, je sais, je devrais renouveler un peu mon stock de blagues. Parce que mettre des cong à la fin de tout et n’importe quoi, pour singer l’accent marseillais, ça commence à …. Je sais. (j’en profite pour vous rappeler que le 24 et 25 avril, il va y avoir la DjangoCong à Marseille, une super convention fr où ça va parler django, encore et encore).

Et, oui, la django-app du mois de janvier arrive vraiment sur le fil, à quelques heures du dépassement de délai. Mais faudra dire ça au crétin qui a décidé qu’une journée ça ne serait que 24h et qu’il fallait obligatoirement dormir chaque nuit, ou presque … (bordeille comment je vais faire en février moi..)

Enfin, je reste dans les délais, c’est le principal. Et pour le deuxième mois consécutif, je fais une petit entorse au principe de cette catégorie, vue que ce mois-ci, encore une fois, ce n’est pas une vrai django-app que je présente, mais un ‘simple’ module python.

0- Et ça sert à quoi  ?

En fait tagcon est ‘inutile’ (donc indispensable vous allez me dire… ne niez pas, je vous ai tous entendu le dire…). Il sert simplement à faciliter l’écriture des templatetags (et surtout des templates tags à argument). On pourrait se dire que c’est assez inutile. Mais en fait, ça permet de gagner un peu de temps et de réduire d’une façon assez intéressante la taille de son code. Donc..

Un petit exemple, tiré de la doc, parce que comme me l’a fait remarquer daks (dont je conseille le blog, qui vient d’arriver dans mes RSS) , ça manque :

from django.contrib.auth.models import User
from django.template import Library
import tagcon

register = Library()

class UserListTag(tagcon.TemplateTag):
    limit = tagcon.IntegerArg(default=10)

    def render(self, context):
        self.resolve(context)
        yield "<ul>"
        for user in User.objects.all()[:self.args.limit]:
            yield "<li>%s</li>" % (user.username,)
        yield "</ul>"

1- Où on le trouve, comment on l’installe, tout ça quoi ?

Alors alors, sur le github qui va bien. (une petite remarque qui a rien à voir, je préfère de loin bitbucket à github … et pas juste parce que mercurial c’est mieux que git).

Une fois qu’on a récupérer le package (par fork si on a un compte github ou avec un petit tar.gz), il y a deux façon de l’installer:

  • un petit python setup.py install
  • en copiant directement le fichier base.py qui se trouve dans tagcon.tagcon (dans ce cas là on pourra renommer base.py en tagcon.py).

2- La documentation.

Alors là… Il n’y a pas grand chose. Un fichier readme qui donne un petit exemple et c’est tout. Après, il vous faudra lire les tests et le fichier source directement. Ce n’est pas donc super fourni, mais d’un autre coté, vous me direz que le module est tellement simple que ça suffit. Et vous ne seriez pas loin d’avoir raison. Mais bon.

3- En conclusion

Au départ, quand j’ai découvert ce petit module (je crois que je dois, encore une fois, remercier benoitc pour cela), je n’étais vraiment pas convaincu de son utilité. Il me semblait presque inutile et puis un peu restrictif en obligeant à utiliser la fonction render (alors que j’ai plus l’habitude d’enregistrer les fichier template html avec le décorateur inclustion_tag). Mais au final, on se ren compte que ça simplifie pas mal les choses et on y prend rapidement goût.

4- dernier paragraphe complètement HS.

Ma liste de django-app à tester est loin d’être vide (avec entre autre piston, haystack,..) et ça ne risque pas de changer, vu que chaque semaine, je découvre une nouvelle app. Toutefois, j’écris ces billets avant tout pour qu’ils soient utile . Donc, si vous connaissez des app que vous adorez et que vous aimerez faire découvrir à tous. Laissez moi leur nom en commentaire et je m’efforcerais de les tester.

Où les middleware envahissent la django-application du mois

Je sais, je suis impardonnable, je n’ai pas fait de billet sur la django-application de décembre. Vous pourriez même rajouter que je le suis encore plus parce que décembre c’est le mois des vacances de Noël et que qui dit vacances dit temps pour écrire un billet.

Oui, mais non. Parce que faut pas croire, ça prend du temps tout ces repas de fêtes. Plein de temps. Sans compter le temps que l’on passe à arpenter les magasins (IRL ou sur le net d’ailleurs) pour trouver des cadeaux. Et sans parler du fait que comme décembre est un mois de vacances, pendant les jours de non-vacances, faut bosser encore plus pour essayer de faire autant que pendant un mois normal, mais en moins de jours.

Autant dire que non, je n’ai pas eu le temps pour la django-app du mois.

Et que vu mon emploi du temps en janvier, ça va être tendu pour le billet de celle de janvier. Mais, mais, dans ma grande mansuétude, j’ai décidé de faire un billet de django app du mois de décembre, en retard.

Et pour une fois, je ne parlerais pas de django-app, mais de middleware. Mais oui, les middleware django, vous savez, ce mécanisme génial qui permet de pluger de petit bout de code à différents niveaux de traitement des requêtes. Ce qui permet de modifier plus ou moins profondément le comportement de django au niveau de la gestion de ses entrées / sorties.

Ca permet de faire plein de trucs, et plus encore.

Aujourd’hui je parlerais de deux d’entre eux, un que j’utilise très souvent et un autre que je vais utiliser sous peu..

1- Loguer les requêtes SQL que fait django

from django.db import connection
from django.template import Template, Context
from django.conf import settings

#
# Log all SQL statements direct to the console (when running in DEBUG)
# Intended for use with the django development server.
#

class SQLLogToConsoleMiddleware:
    def process_response(self, request, response):
        if settings.DEBUG and connection.queries:
            time = sum([float(q['time']) for q in connection.queries])        
            t = Template("{{count}} quer{{count|pluralize:"y,ies"}} in {{time}} seconds:\n\n{% for sql in sqllog %}[{{forloop.counter}}] {{sql.time}}s: {{sql.sql|safe}}{% if not forloop.last %}\n\n{% endif %}{% endfor %}")
            print t.render(Context({'sqllog':connection.queries,'count':len(connection.queries),'time':time}))                
        return response

J’ai trouvé ce tout petit middleware sur djangosnippets. Il se contente d’afficher la liste de toutes les requêtes SQL faites par django, en donnant le temps pris par leur execution.

C’est bien utile pour vérifier que ces vues ne font pas de la merde et pour tenter d’optimiser en factorisant des choses.

2- Django-maintenancemode

Celui-là, je l’ai découvert au détour d’une conversation sur #django-fr. Carrément plus pratique que la bête page html qui dit ‘en maintenance’, utile à connaître et à avoir dans sa django-boîte à outil.

Django-ROA ou… Mince je trouve pas de jeux de mots là

Ça sera bien la première fois que je ne fais pas de jeux de mots dans le titre d’un billet la Django-app du mois. Mais là, je n’ai vraiment pas d’inspiration et comme je suis sur un timing plutôt serré (le billet devant être publié d’ici au plus tard 4h20 pour pouvoir prétendre à être un billet de novembre), je ne vais pas trop attendre qu’elle n’arrive. Je me rattraperai le mois prochain (je pense parler de piston le mois prochain, tout un poème…).

Django-ROA donc, cette jolie app est développée par David Larlet que j’ai déjà cité dans mes précédents billets. Il permet de gérer des ressources distantes normalement accessibles en REST, en passant à travers l’ORM de django (et donc les modèles Django).

Et oui, ça permet, d’une façon plus que facile de faire comme si des modèles distants étaient des modèles locaux.

Le petit schéma suivant (que j’ai très vilainement récupéré du site de David, sur le billet parlant de Django-ROA) explique tout, bien mieux que ne le ferraient mille de mes mots.

django-roa-diagram-petit

Bien entendu, on est pas obligé de se limiter à faire communiquer notre Django à un autre Django distant. On peut se connecter à tout ce qui a une interface HTTP. Op timeline de Twitter, Op n’importe quelle BD discutant le HTTP…

Je vois à vos sourires béats que vous êtes en train de comprendre combien Django-ROA peut être utile. Et vous avez raison.

1- Où on le trouve, comment on l’installe, tout ça quoi ?

Alors on le trouve sur la page bitbucket qui lui est consacré. Pour l’installation, il y a deux possibilités :

  • soit avec hg et op on récupère la dernière version des sources
  • soit avec easy_install

Attention toutefois, le package easy_install contient une version du trunk Django 1.2. Si vous ne voulez pas l’utiliser, il faudra penser à supprimer le répertoire en question.

Dans les deux cas Django-roa vient avec une version de restkit et une version de Django-piston. Si vous avez déjà ces deux librairies là, là aussi il faudra penser à faire le nettoyage.

Enfin, c’est important, si vous êtes en Django < trunk, il vous faudra patcher votre Django pour pouvoir utiliser les many to many en distant. Si vous êtes en Django SVN, il vous faudra attendre que David ait rendu Django-ROA compatible Django 1.2 (c’est peut-être déjà le cas d’ailleurs).

2- Niveau documentation

Il y a le wiki du bitbucket ainsi que l’article du blog de David dont j’ai déjà donné le lien (mais je le redonne pour les étourdis). Il y a également le code source des tests, qui permet de bien comprendre comment tout fonctionne. Et je vous recommande vraiment de lire le code des tests si vous voulez comprendre.

3- Qu’est-ce qu’on fait et comment on le fait ?

Qu’est-ce qu’on fait, je vous l’ai déjà dit. Faut suivre un peu. On connecte notre Django à notre Django (ou d’autre base distante, voir l’exemple avec Twitter). Mais ce qu’il faut savoir c’est que Django-ROA permet de gérer la partie serveur et la partie client, dans le cas où vous développez vous même la partie ‘Django distante’.

Maintenant Django-ROA est encore en dev, et il peut être utile de connaître quelques petits tuyaux, que bien entendu, je vais vous donner.

4- Les tuyaux de Jmad…

4.1- Erreur 500 côté serveur

Sur la partie serveur, il se peut que vous vous trouviez avec des erreurs 500 assez silencieuses. C’est moi ce que j’ai eu. Il se trouve que c’est dû au logging.debug et à un problème (allez savoir pourquoi) d’encodage UTF-8. Enlevez les logging et tout roule. Je n’ai pas eu le temps de chercher et faire remonter à David le pourquoi du comment de ce problème, mais comme je me suis creusé la tête quelques temps avant de trouver le problème, je préfère vous informer.

4.2- Sérialisation…

Par défaut, on peut sérialiser les objets de trois façons :

  • en JSON,
  • en XML,
  • en utilisant le sérialiseur fait par David pour les tests qui est un sérialiseur XML un peu modifié.

Allez savoir pourquoi, mais pour moi, seul le troisième daignait fonctionner.

4.3- Authentification

Pour l’instant l’authentification sur les services distants n’est pas gérée. Si vous en avez absolument besoin, n’hésitez pas à envoyer un mail à David.

5- Conclusion

Django-ROA est encore un module en dev, il manque quelques fonctionnalités qui pourraient le faire passer du statut d’app intéressante et utile à celui d’app complétement indispensable. Mais il est d’ors est déjà bien utile, quand des problématiques de communication entre bases distantes se mettent à apparaître.

Il me semble juste que l’on devrait changer son nom, pour par exemple Django-CROA. Ça m’aurait permis d’avoir un bien meilleur titre du genre Django-CROA et le crapaud est en toi, ou alors Django-CROA , l’app qui voulait devenir aussi grosse qu’un bœuf…) enfin, tant pis.