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.

Les nouveautés de django 1.2 alpha

Avant de commencer à te faire perdre ton temps, je tiens à te prévenir cher lecteur. Si tu as lu la release note de django 1.2 alpha 1, tu n’apprendras rien de plus en lisant ce petit billet.

Pourquoi alors l’écrire ?

Au cas où tu n’aurais pas encore lu la release note et que lire du français t’amuse plus que lire de l’anglais. Et puis comme ça, en plus, tu as le lien vers la release note.

1- Les trucs nouveaux

1.1- protection contre les attaques CSRF.

Les attaques CSRF (Cross-Site Request Foregery) sont rendus  possible par le partage des données de login/session entre les différents onglets d’un navigateur. Du coup, si vous êtes logués sur un site quelconque (prenons facebook comme exemple) et que vous allez sur le site d’un vilain méchant pirate, le vilain méchant pirate pourrait faire des actions sur Facebook, comme si c’était vous qui les faisiez. (Bon pour pouvoir faire cela, il faut que vous cliquiez sur un lien du site du vilain pirate, ou que vous soumettiez un formulaire ou que vous executiez du js).

Django implémente maintenant une façon cool de s’en protéger. (avant il existait un middleware pour le faire). Moralité, si Facebook était en django 1.2, les attaques CSRF ne seraient pas possible.

1.2- Backends des emails

On peut maintenant configurer la façon que django aura d’envoyer des emails. Sympa pour pouvoir debugger et tester les envois d’emails, ça évitera d’avoir à passer par des simulateurs de SMTP.

1.3- Le framework d’envoi de messages

Il remplacera l’ancienne API d’envoi de message et apparemment, il va être juste terrible. Les users authentifiés ou anonyme pourront en envoyer, on pourra les stocket en session ou en cookie, gérer des levels, des tags, que du bon quoi

1.4- Support des multiples bases de données

Alors ça, je l’attendais avec une impatience extrême. On pourra maintenant dire à django de se connecter à X bd différentes, choisir pour chaque requête bd sur quelle base on veut la faire ou où est ce que l’on veut sauver une instance de modèle. Que du bon quoi. Pour ne pas dire de la tuerie

1.5- Un tag if coolos

Là on peut résumer en une phrase : ‘Fini le ifnotequal a b et vive le if a != b’.

Les opérateurs de comparaisons sont enfin supporté. On pourra donc utiliser :

  • ==
  • !=
  • <
  • >
  • <=
  • >=
  • in
  • et and or et not (qui fonctionnaient déjà).

Et en plus, on pourra utiliser des filtres en même temps. Avec un {% if  inst1.var1|bla == inst2.var2|tut %}

Le pied je vous dis.

1.6- Gestion du cache des templates

On pourra configurer un truc de gestion de cache des templates. Et ça, c’est bien.

1.7- Clés en BD

On peut maintenant utiliser les naturals keys dans les fixtures (j’ai pas trouvé de traduction française qui me convenait). Ce qui peut-être bien sympa quand par exemple on a des fixtures qui bossent avec des content types (au hasard hein )

Et on peut maintenant utiliser des int de 64 bits avec le BigIntegerField .

1.8- En vrac

  • une commande en plus sur le runtest qui permet de faire sortir le lanceur de test dés qu’il y a une erreur.
  • Une amélioration de la localisation pour les dates et les nombres qui seront affichés (si l’option est activée) de la façon qui va bien en fonction de la locale.
  • L’ajout de la  propriété readonly_fields pour les champs non éditable (enfin)
  • la possibilité de customiser les couleurs pour les highlight dans la parti admin.

2- Les trucs  obsolètes ou incompatibles

Bon alors déjà, une nouvelle qui va faire que tout le monde va respirer, dans le 1.2 les trucs obsolètes seront encore supportés. Le support n’en sera supprimé que dans la version 1.4.  Ça laisse donc un peu de temps pour organiser ses migrations.

2.1- Le middleware CSRF

Forcément si la protection anti CSRF est refait d’une manière mieux, l’ancienne manière devient obsolète.

2.2- SMTPConnection

Ceux qui utilisaient la classe SMTPConnection pour envoyer des mails devront changer leur code. Heureusement les modifs sont légère (il suffit apparemment de remplacer l’appel au constructeur de la classe par un appel a get_connection () )

2.3- La configuration de la base de données

Forcément ça change. Faudra passer dans la syntaxe multidb, même si on a qu’une seule db.

2.4- L’API d’envoi de message.

Là encore, faut passer à la nouvelle version. Mais ça n’a pas l’air super compliqué. Du replace de nom de fonction et ça devrait le faire.

2.5- Les helpers de formatage de date.

Les fonctions django.utils.translation.get_date_formats() et django.utils.translation.get_partial_date_formats() sont obsolètes et il faudra les remplacer par django.utils.formats.get_format()

2.6- En vrac

  • Du fait des nouvelles fonctionnalités du if, appeler des variable ‘and’, ‘or’ ou ‘not’ est encore moins une bonne idée, vu que vous allez vous manger des TemplateSyntaxError. Bon de toute façon, c’était déjà une très très mauvaise idée d’appeler des variables ‘and’, ‘or’ ou ‘not’, donc …
  • Le LazyObject. Ceux qui utilisaient cette classe non documentée vont devoir modifier leur façon de l’utiliser.
  • Modification de ce que contient le __dict__ dans les instances de Model : Jusqu’à présent le __dict__ ne contenait que les attributs qui correspondaient au champ du modèle. Maintenant il contient un attribut _state qui sert à gérer les db multiple. Ceux qui itere sur le __dict__ de Model devront faire attention à filtrer le _state
  • les fonction get_db_prep_* des Fields ont changé de signature (et il y en a 2 de plus get_db_prep_save et get_prep_lookup )
  • du fait de l’utilisation du cache loader, il faut bien vérifier que les templates tags utilisés sont bien thread-safe (je sais pas pourquoi je sens que ce point là va être le point de départ de dizaines de touffes de cheveux de geeks arrachées).
  • Code de retour du lanceur de test : Le code de retour du lanceur de test ne correspond plus au nombre de test raté. C’est maintenant 0 si aucun test n’a merdé, 1 si il y a eu des merdes.

3- Conclusion

Que du bon dans cette nouvelle version donc. Et en plus pas spécialement beaucoup de modifications à faire pour profiter des nouvelles améliorations. Vivement le 9 mars que la stable sorte quoi. 🙂

Django : Dict’s Rivers, toi aussi devient fan.

C’est benoitc qui en me parlant des dicts fournis par Django m’a fait découvrir les quelques classes bien utiles définis dans datastructures.py du module utils de django.

Ce sont donc, comme le titre de ce petit billet (plus mémo que billet) l’explicite bien des dicts.

1- Le MergeDict

On le construit en lui donnant plusieurs dict. Il en fait une espèce de gros dict virtuel qui contient tout les dicts. Si on tente une opération sur une clé (un has_key, un get ou un __get_item__ ) il la cherchera  dans tout les dicts. Par contre si elle est présente dans plusieurs dict, il utilisera la première occurrence qu’il trouve (pour le get par exemple).

Un dict qui peut être utile, surement.

2- Le MultiValueDict

Là encore, le nom parle de lui-même. C’est donc un dict qui permet d’avoir non pas une seule valeur, mais une liste de valeur par clé. En plus des fonctions classiques des dicts, elle offre donc getlist, setlist, setlistdefault et appendlist pour pouvoir interagir avec les instances de la classe.

3- Le DotExpandedDict

Ce Dict est un peu un OVNI. En fait la classe se contente de redéfinir un constructeur qui va vous permettre de construire des dicts qui contiennent eux mêmes des dicts et celant en passant en paramètres des chaînes de caractères construite d’une manière précise (en utilisant des .)

Un exemple (celui donné dans le code) sera surement plus parlant.

>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], \
'person.1.lastname': ['Willison'], \
'person.2.firstname': ['Adrian'], \
'person.2.lastname': ['Holovaty']})
>>> d
{'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname':['Holovaty'], 'firstname': ['Adrian']}}}
>>> d['person']
{'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}
>>> d['person']['1']
{'lastname': ['Willison'], 'firstname': ['Simon']}

4- Le SortedDict

C’est mon préféré, tout simplement parce que j’ai déjà du l’utiliser et qu’il m’a permis de ne pas avoir à le recoder moi-même. Il se contente de garder l’ordre dans lequel on insère des choses dedans. Pour être clair, lorsque l’on itère dessus, il va utiliser l’ordre d’insertion des données. Et ça, c’est vraiment cool.

5- Le reste

il reste encore deux classes dans ce sympathique petit fichier.

Une ImmutableList, qui fonctionne comme un tuple et qui est complétement imutable (et l’on peut même choisir le message d’erreur qu’il vous envoie à la figure pour vous le dire qu’il est immutable.

Un DictWrapper qui permet de s’assurer que les valeurs contenues dans le dict seront passées à travers une fonction avant d’être donné à l’utilisateur, si la clé en rapport commence par un préfix donné.

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.

Django-tagging, et le tag est en toi

Me revoilà donc pour le désormais presque célèbre billet mensuel de la django-app du mois. Comme d’habitude, je le fais sur le fils, limite à être en retard. Mais c’est bien normal, après tout il me faut bien un mois complet pour choisir, tester à fond et rédiger un magnifique billet concernant l’app du mois.

L’app d’octobre est donc django-tagging. Qui comme son nom l’indique sert à taguer des models.

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

On le trouve, très simplement sur google-code, sur sa page projet.  Pour l’installation, là aussi c’est du très classique :

  • pip
  • easy_install
  • télécharger un tar.gz
  • utiliser le svn de google-code

moi j’ai choisi, une fois n’est pas coutume d’utiliser easy_install.

Niveau documentation ?

Un fichier en ReStructuredText, accessible directement sur le site et présent dans les sources donne la doc et des exemples d’utilisation. Il n’est d’ailleurs par forcément à jour. Certaines fonctionnalités décrites comme étant dans la version de dev sont en fait dans la 0.3

En plus, trois petites pages sont présentes sur le wiki :

  • une pour parler d’un tips d’utilisation (avec des properties)
  • une pour les incompatibilité entre versions
  • une pour les idées et le planning

Ils sont où les murs alors ? ( ou qu’est ce qu’on peut faire avec django-tagging)

Ok, ce titre de chapitre est surement le plus pourris de ma carrière de créateur de titre de chapitre, mais tant pis j’assume.

Le configurer

Il y a quelques possibilité de configuration, en setant des variables dans le settings.py du projet. On peut par exemple forcer à ce que les tags soient en minuscule ou donner la longueur maxi d’un tag.

L’utiliser

On peut donc taguer des instances de model. Mais bon en disant cela, j’ai rien dit. En fait on peut register des models pour pouvoir ensuite simplement rajouter des tags (ou les lister) aux instances de ces models.

On peut également passer directement par les managers de Tags, fournit par l’app, pour taguer des instances.

L’utiliser encore plus

il y a quelques fonctions utilitaires fournis avec l’app.

On pourra par exemple ( avec la fonction get_intersection_by_model) récupéré le sous-ensemble des instances contenu dans le queryset passé en paramêtre 1 qui sont tagués avec tout les tags d’une liste passé en paramêtre 2

De même avoir toutes les instances d’un models tagués par un ou plusieurs tags est possible avec la fonction get_by_model, mais aussi les unions d’instance ou les groupe d’instance ayant les même tag qu’un autre objet …

Et aussi (et presque surtout aurais-je envie de dire) la fonction calculate_cloud qui permet de calculer le nuage de tag en calculant une taille de font pour chacun des tags passé en paramètre. (l’algorithme utilisé pour le calcul est configurable, en plus)

afficher les tags

Avec 4 templatestags différent pour afficher le nuage de tag, tout les tags d’un objet, tout les objets (d’un model précis) tagués avec un tag précis, ou tout les tags qui sont reliés à un model (enfin à ses instances, vous m’avez compris)

Conclusion.

Même si la façon d’ajouter un tag peu sembler un peu alambiqué (pour pouvoir avoir des tags avec des espaces, ou avec des espaces plus des guillemets, etc .. ) , c’est vraiment une bonne app, qui ne fait qu’une chose, mais qui le fait très bien. Donc, je ne peux que conseiller son utilisation.

Le built-in any, vous aussi vous allez aimer les sucettes à l’any ….

J’ai mis quelques temps à le découvrir ce built-in, pour l’oublier presque aussi vite. Je l’ai redécouvert au détour d’une conversation python au boulot.

A quoi sert-il donc ? En fait ‘à rien’, simplement à alléger l’écriture (niveau perf, je ne sais pas si cela change quelque chose, ça par contre)

any prend un seul paramêtre, un iterable et renvoie True dés que l’un des iterables est vrai. Si je cite la doc python, any est équivalent à une fonction définie comme suit :

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

un petit exemple sur une recherche de sous-chaine dans des chaines :

avant :

for word in list_words:
    if word.find(substring) != -1:
        return True
return False

après :

return any ( word.find(substring) != -1 for word in list_words )

C’est plus léger, tout le monde sera d’accord avec moi …

Et puis, vu qu’on y est, il existe aussi le built-ins all qui prend lui aussi un itérable en paramètre et renvoie True si tout les éléments de l’itérable sont True.
(note de bas de billet : oui je sais, mes titres de billets sont toujours aussi … mais j’assume)

Les erreurs 404 et 500 en django.

Les erreurs 404 et les erreur 500 sont les deux erreurs les plus courantes sur le web. Quand on est pas en mode debug (vu que là c’est le mode debug qui gére le tout, avec une jolie traceback pour l’erreur 500), il faut s’occuper de l’affichage des dites pages.

Et par défaut, il n’y a pas de templates pour les deux erreurs. Même pas un petit template tout vide. Non rien. Ce qui fait que lorsqu’on génère une 404, comme django ne trouve pas le template, boum on se prend une 500 dans les dents, qui elle même râle parce qu’elle ne trouve pas son template.

Template 404 et 500

Les templates doivent se nommer, fort intelligemment 404.html et 500.html. Ces deux fichiers de templates doivent se trouver, c’est important, à la racine de votre répertoire contenant les templates.

Spécificités de la 404

il sera passé une variable à votre template 404 , request_path , qui contiendra l’URL qui a généré la 404. Vos contextes processors seront également appelés et donc vous pourrez les utiliser dans votre template.

Spécificités de la 500

Il n’est rien passé au template 500, histoire de ne pas, potentiellement, aggraver les problèmes, pas une seule variable.

Les handlers

Il est possible que redéfinir des templates ne vous suffisent pas. C’est peut-être fort improbable, mais possible. Ce cas là a été prévu. Il vous suffit de définir vos views spécifique et de enregistrer dans les deux handlers qui vont bien à savoir handler404 et handler500.

Vous voilà maintenant paré. Amusez vous bien avec vos templates persos de page d’erreur.

Django registration, et avoir des users devient facile.

Tout d’abord, mes plus plates excuses à vous tous, fidèles lecteurs de mon petit espace qui attendiez avec d’abord joie, puis impatience, puis tristesse et désespoir, le billet de la django app du mois de septembre.

Alors oui, nous sommes le premier octobre et le billet de la django app de septembre n’a pas encore été posté. Oui, c’est une honte de lancer ainsi une si bonne idée et de ne pas suivre le principe même de la bonne idée de le deuxième mois. Oui, je reconnais tout cela. Mais votre honneur, je plaide coupa.. pardon innocent.

Ce n’est pas de ma faute si je n’ai pas écrit ce billet. Mon chien (comment ça je n’ai pas de chien?) a mangé mes devoi.. pardon mon cable réseau. Et puis c’est sans parler du débarquement des ET, qui a eu lieu dans mon jardin (comment ça y a pas de jardin dans mon appart?) et qui a ruiné ma pelouse.

Bon, trêve de bêtises. En fait il y a deux raisons à ce retard sur le deuxième billet djangoapp du mois (et aussi sur mon relatif silence sur ce blog). Deux raisons très simples :

  • Une grosse période bien chaude au boulot, avec suffisamment de boulot pour y bosser soir et week-end.
  • Le fait que la troisième occurrence du SPLLOS (le salon professionnel des logiciels libres qui aura lieu à marseille, le 13 octobre) se rapproche à grand pas (ben oui le 13 octobre) et qu’en temps que président de l’association qui l’organise (Libertis, l’association des boites qui font du libre en PACA), j’ai pas mal de truc à gérer (d’ailleurs je profite de ce billet, même si ils ne le liront jamais, pour remercier plus qu’un peu les membres de l’asso qui bossent aussi sur ce sujet, heureusement qu’on est à plusieurs sur le truc, sinon … )

Et, comme les deux points que je cite au dessus sont toujours d’actualité, le billet du mois de septembre (mais oui on est encore, presque, en septembre) sera un billet court, sur une app que beaucoup doivent connaître mais qui à l’avantage d’être suffisament petite pour être tester avec peu de temps  : J’ai nommé django-registration. Qui sert à la registration des users (désolé ça fait depuis le début du billet que je voulais le faire cet anglicisme).

1- A quoi ça sert , où on le trouve, comment on l’installe ?

1.1 Le pourquoi du comment

Utiliser django-registration c’est bien parce que cela permet de ne pas réinventer la roue et donc de ne pas perdre du temps à développer un système d’enregistrement/activation/ utilisateurs.

1.2 Où on la trouve ?

Sur bitbucket, il y a un repo avec un wiki bien sympa , ici : http://bitbucket.org/ubernostrum/django-registration/

1.3 Comment on l’installe ?

Il y a trois manière pour l’installer, par easy_install , par pypi ou avec les bonnes vieilles sources (hg cloneeeee) et un python manage setup.py.
Personnellement j’ai une préférence pour la troisième méthode, la doc étant incluses dans les sources, je trouve ça plus facile d’avoir les sources du truc que je met à jour de temps en temps.

2- Mais ça fait quoi django-registration, pour de vrai ?

Django registration met un place un système complet d’enregistrement des users.

A savoir, vous avez la vue qui gère le fait qu’un user veut s’inscrire et va remplir un joli petit formulaire.

Une fois le formulaire submit, django va créer un compte user inactif et envoyer un mail qui contiendra une clé d’activation. L’utilisateur qui vient de submit sa demande d’enregistrement verra alors ensuite apparaître une jolie page lui disant d’aller vérifier ses mails et d’activer son compte.

Truc sympa, l’app gére le fait d’interdire certains provider d’emails jetable ou l’interdiction de créer un compte avec un email déjà utilisé.

Cerise sur le gâteau, il y a même un petit script (qui utilise les commandes django) qui permettra de supprimer les comptes qui n’ont pas été activés et qui sont considérés comme expirés.

2.1 Et la localisation ?

Elle y est, dans tout plein de langues (y compris le français, bien entendu)

3- La doc ?

Bien fournie, très précise et claire, il n’y a vraiment rien à redire.

Une fois qu’on a installé l’app, on a plus rien à faire alors ?

Ben en fait si, parce qu’il n’y a aucun template de fournis, même pas à titre d’exemple. Il faut donc ‘tous’ les faire, mais c’est assez rapide. Et puis là aussi, la doc est vraiment bien faite et détaille précisément chaque variable du contexte de chaque view. Faire les templates n’est donc pas vraiment difficile.

4- En conclusion

Installez la et utilisez la.

Des blocks dans des blocks dans des blocks , dans des …

Tout ceux qui font du django, ont, un jour, utilisés des blocks pour écrire un template. Pour rappel, un block c’est un moyen de délimiter un ’bout’ de template.

A quoi ca sert un block ? Très rapide rappel

Imaginons que vous faites un blog. Votre blog peut afficher soit un post, soit une liste de post, soit une catégorie, soit une liste de catégorie. Dans tout les cas, vous aurez des menus à droites et à gauches et même au dessus.
Vous allez peut-être décider de faire un template ‘base’ où vous allez définir les choses qui ne changeront jamais, ici les menus.
Ensuite il faut trouver une façon simple de pouvoir soit afficher un post, soit une catégorie, etc etc ..

Rien de plus simple. Dans la base vous définissez un block content par exemple :

{% block content %}
{% endblock %}

Maintenant dans votre template qui s’occupe d’afficher les posts, il suffira de dire que vous étendez base puis de redéfinir le block content et op, vous aurez à la fois tout vos menus définis dans base mais aussi votre nouveau content.

{% extends "base.html" %}

{% block content %}
     {{post}}
{% endblock %}

Bien entendu, on est pas obligé de redéfinir tout les blocks de template qu’on étends. Si on ne redéfinit pas un block , le contenu du block parent sera utilisé. (Par exemple, si on reprend l’idée du blog, ce n’est pas seulement un block content qu’il faut définir, mais aussi un block pour chacun de nos menus. Ces block ne seront pas redéfinis dans le template post, c’est donc ceux de base qui seront utilisés)

des blocks dans des blocks.

Jusqu’à présent, je n’ai fait que faire un très rapide rappel de ce que c’était qu’un block en django. (Pour ceux qui veulent en savoir plus, la doc de django est là pour ça).

La petite astuce que je voulais mettre en lumière dans ce billet arrive maintenant. En fait c’est tout simple, c’est qu’on peut parfaitement imbriquer des blocks dans d’autre.

Ceci :

{% block content %}

    {% block content_intra_content %}

    {% endblock %}

{% endblock %}

Fonctionne parfaitement. A quoi cela pourrait servir ? Pourquoi ne pas faire deux blocks l’un en dessous de l’autre ?

Pour la première question, je me suis creusé la tête pour trouver un exemple. Je crois en avoir trouvé un. Imaginons qu’on doit afficher différentes données, toute de la même manière. Mais que par contre , en fonction des données en question , on a un menu ‘Actions possibles’ différents.

Pour reprendre mon exemple de blog, cela serait afficher la liste des catégories ou la listes des posts.

On pourrait donc décider de faire les choses ainsi  dans le template liste :

{% extends "base.html" %}

    {% block content %}

    {% block actions  %}

{% endblock %}

    {% block content_intra_content %}
         Ici on affiche des trucs ...
    {% endblock %}
{% endblock %}

puis dans le template liste_categorie :

{% extends "liste.html" %}

    {% block actions  %}
         {{categorie_actions}}
    {% endblock %}

Je ne suis pas sur que ce soit le meilleur exemple, ni même qu’au final, l’imbrication des blocks aient une quelconque utilité, mais comme en testant, je me suis rendu compte que c’était possible, je me suis dit que j’allais en parler (Et comme ça si des gens ont un avis sur l’utilité de cette pratique, je les aurais en commentaire)

Deux derniers petits trucs

Le tags {{ block.super }} qui permet dans un block fils de récupérer le contenu d’un block père pour l’afficher. A utiliser quand on ne veut pas redéfinir un block mais simplement l’enrichir.
Il est possible de remettre le nom du block dans le tags de fin de block comme ceci :

{% extends "base.html" %}

{% block content %}

{% endblock content  %}

Ca ne sert à rien, à part à rendre plus clair les choses.

L’algèbre du Q (et du queryset)

Oui, je sais, mon titre de billet n’est pas des plus fin.. Tans pis, c’est la faute au surmenage.

J’avais déjà parlé des objets Q dans un précédent billet. Pour mémoire les objets Q sont des objets django qui permettent de faire de filtrer des requêtes BD d’une façon plus poussée qu’en simplement chainant des appels à filter.

L’algèbre des Q

Les opérateurs ET (&) et OU ( | ) fonctionne sur les objects Q. On peut les chainer, en faire des expressions complexes en parenthésant sans aucun problème.

L’algèbre des queryset

Les queryset sont des objets itérable qui sont renvoyés, par, entre autre, la fonction filter et qui stockent le résultat d’une requête BD. On s’en sert aussi pour remplir les différents composants ‘à choix’ d’un formulaire (selectlist,etc… ).

On ne peut pas concaténer deux queryset comme on pourrait le faire avec deux listes avec par exemple L1 + L2. Mais les queryset supporte les opérations logique. On peut donc là aussi faire des OU (ce qui revient à les concaténer) et des ET pour trouver l’intersection entre deux queryset.

Et c’est, plus que bien utile.

Django Extensions, le couteau suisse du djangonaute.

Une nouvelle catégorie apparaît (oui je sais, encore une alors que certaines restent désespérément vide, mais grâce à la magie de wordpress, vous ne le savez pas, vu que les catégories vides n’apparaissent pas… ), la Django App du mois. Tout est dit dans le nom, tout les mois, en fin de mois, je posterais un petit billet sur une django app que j’aurais testé pendant le mois. Enfin, ça c’est le principe, est ce que je vais tout les mois avoir le temps de chercher/choisir/tester une django app.. Ça, rien n’est moins sur. (d’ailleurs j’en profite, si vous avez des idées de django app, les commentaires sont là pour ça).

Pour ce premier numéro, la django App qui a la chance d’être la django App d’août est Django Extensions. (tiens, je viens d’avoir une idée, un calendrier des DjangoApp, que les djangonautes, ou les routier, pourraient accrocher dans leur bureau ou leur camion).

1- A quoi elle sert ?

Django Extensions est une application d’aide au développement. Elle rajoute plein de commande au manage.py, commandes tellement indispensable qu’on se demande comment l’on avait pu faire sans.

Elle rajoute aussi quelques Database Model Fiels et  Database Model. Et comme si cela ne suffisait pas on gagne aussi, pour le même prix, une extension pour la gestion des ForeignKey du coté admin.

2- Et plus en détail ?

2.1 Les commandes en plus

Je vais me limiter à décrire quelqu’une des commandes que vous pourrez utiliser avec Django Extensions, celles que moi, j’utilise le plus souvent.

  • generate_secret_key

elle permet de générer une secret key pour son projet. Ca a l’air tout con et inutile, mais en fait non. Quand on utilise un gestionnaire de source pour déployer rapido son projet et que donc on ne passe pas par la commande de création de projet, et ben en fait c’est super utile.

  • create_app

rien de plus que la commande de base sauf que l’on peut donner en plus un répertoire de template à utiliser

  • reset_db

qui n’a pas eu besoin de reset 42 fois par jour sa bd ? Et passer soit par le client ligne de commande soit par les interface web d’admin, ça devient rapidement très chiant. Pour tout ces djangonautes là (dont je fais parti) reset_db c’est le paradis.

  • runscript

lance un script dans l’environnement django.

  • runserver_plus

l’une des (si ce n’est pas la) commandes la plus utile de toute l’extension. Elle nécessite d’avoir Werkzeug installé (mais un petit easy_install et c’est bon). Et elle permet ensuite de lancer le serveur de dev avec le debugguer de Werkzeug. Et là, c’est le pied. A chaque exception reçu, on se retrouve avec une vrai interface de debugger dans notre page web. On peut ouvrir des consoles interractive un peu partout (à tout les pas d’appel de fonction), on peut voir l’état courant des variables, le code de chaque fonctions tracées ). C’est juste ultime.

  • shell_plus

celle là aussi est une commande indispensable. Elle vous permet de lancer un shell qui a déjà importé tout vos models. Lorsqu’on utilise comme moi, assez souvent le shell pour faire quelques petits tests, vérifications, on se rend vite compte du gain de temps.

  • dumpscript

qui permet de générer un script python à partir des données contenu dans une base de donnée à un instant t. dumpscrit fonctionne pour toute une app ou juste un model d’app.

2.2 Le système de job

Django Extensions rajoute un mécanisme complet de job. Un job est une classe python qui dérive de BaseJob et qui implémente la fonction execute (self).

Les jobs se définissent par app django. Pour mettre en place le système de jobs pour une app, il suffira d’utiliser la commande create_jobs en lui donnant le nom de l’app en question. Django Extensions créera alors l’architecture de répertoire qui va bien.

Une fois que l’on a créé ses jobs, on peut les configurer pour qu’ils soient executés toutes les heures, les jours, les semaines, les mois. On peut aussi demander l’exécution d’un ou de plusieurs jobs en commande manage.py.

3- Comment on l’installe, où on le trouve ?

Django extensions étant hosté par google code, il suffit d’aller sur son espace google code se trouvant là http://code.google.com/p/django-command-extensions/

Pour l’installation deux possibilités :

  • télécharger la derniere versions sur le site web puis faire un simple python setup.py install
  • lancer un easy_sintall

ensuite, il vous suffira, pour chaque projet dans lequel vous voulez l’utiliser, d’ajouter django_extensions dans votre INSTALLED_APPS .

Et c’est tout.

4- Et la doc ?

Vous en trouverez sur le google code. Plutôt complète et claire. Il y a même un lien vers un screencast.

5- En conclusion

Une application à utiliser, sans aucune modération et qui fait vraiment gagner énormément de temps.

Xmpp en python, petit tour des possibilités

Pour ce premier post parlant d’XMPP, je ne vais pas faire trop compliqué, je vais me contenter de faire un petit tour des possibilités qui s’offre au gentil et innocent développeur python qui, ayant découvert le monde merveilleux d’XMPP se décide à utiliser ce joli protocole dans un de ces programmes python.

Il faut dire, que lorsque j’ai commencé à m’intéresser à ce sujet, il y a un peu plus d’un an, j’ai été surpris par le peu de librairies maintenues et proposant un peu plus que la simple paire réception/envoi de message. Aujourd’hui, la situation n’a pas vraiment changé. C’est, je trouve, assez étrange, surtout que cette situation ne se retrouve pas dans d’autre langages qui ont pléthore de librairie (un seul exemple, en Java).

1- Les mortes, ou presque.

Parmi les librairies zombies, je vais en citer deux Zymb  ou jabber.py

Il semble ne plus avoir eu un seul mouvement sur leur deux sites respectifs depuis 2007 ou 2003. La doc est quasiment inexistante, les exemples de même. A ne surtout pas choisir donc, si vous voulez commencer à bidouiller avec XMPP.

2- La  librairie sans code

Sleekxmpp est une petite librairie hébergé sur google code. Je n’ai pas l’impression qu’elle bouge beaucoup au niveau du code, même si des bugs ont été commentés très récemment. Mais, il y a comme un problème. Impossible de récupérer le code source de la dite lib, le svn est vide.

3- La plus complète

Celle qui est, sans aucun doute, la plus complète, celle la version modifié de xmpppy qui est utilisée par gajim. Elle gère énormément de XEP, son développent est continue, le rêve quoi. Sauf que.. j’ai essayé de l’utiliser et le faire sans devoir utiliser tout le code de gajim, c’est un peu (voir beaucoup) mission impossible. Sans compter qu’elle existe en de multiple version (quand je l’ai testé, le support du BOSH était dans une version bien spécifique de la lib, une des branches SVN, je ne sais pas si c’est toujours le cas).

4- Les autres

Xmpppy en version originale ou pyxmp. Elles gèrent un certain nombre de XEP, pas une panacée mais un peu plus que le simple envoi/réception de message. La doc a au moins le mérite d’exister. Une doc API avec même quelques petits exemple de code. J’ai un peu utilisé Xmpppy et elle est pas mal, surtout quand on veut utiliser une librairie légère (sans être ridicule) dans un prog où le XMPP n’est pas central mais une partie, au milieu des autres.

5- Celle que j’utilise.

La librairie que j’utilise actuellement est en fait, au final, presque celle avec laquelle j’ai commencé à faire joujou avec XMPP en python. J’ai commencé en utilisant Twisted words qui est la partie consacré aux Instants Messaging (et IRC) dans Twisted. Autant dire que c’est le parent pauvre de Twisted, peu de doc, peu d’exemple (mais relativement, par rapport aux autres lib, beaucoup), aucune gestion de XEP. Le concept de twisted words xmpp était simple :
Vous avez la puissance de twisted, on vous fournit un moyen de vous connecter et de brancher des callback sur des cheminx XPATH, à vous de faire le reste. D’une simplicité magnifique.

Sauf que, même si le concept est élégant, avoir quelque XEP de gérer, out of the box, c’est un peu mieux, quand on veut juste utiliser le XMPP et pas devenir développeur de lib XMPP.

C’est pour cela que j’utilise Wokkel, une surcouche à Twisted words qui gèrent quelques XEP (dont pubsub). J’ai ainsi quelques XEP (même si je pourrais en avoir plus en essayant d’utiliser la lib de gajim) et je bénéficie de toute la puissance de Twisted.

Une particularité de Twisted (et wokkel) c’est que ce sont des librairies qui sont prévues pour développer des clients ou des serveurs. Certaines fonctionnalités sont donc gérer pour les deux cotés, que pour le coté serveur ou que pour le coté client.

Une autre particularité, qui peut être ennuyeuse, c’est que twisted se fonde sur l’utilisation de ‘reactor’ et qu’il peut parfois être un peu difficile de concilier la façon de fonctionner de twisted avec celle de l’application dans laquelle on veut l’intégrer.