Un Electron Libre...

Aller au contenu | Aller au menu | Aller à la recherche

Python - Django

Tout ce qui touche de près ou de loin à Python/Django

Fil des billets - Fil des commentaires

mardi 25 mars 2008

Lecture : Programmation Python

Je viens de terminer la lecture de "Programmation Python", qui possède d'ailleurs son |propre site dédié au livre|http://programmation-python.org/sections/blog|fr].

J'ai trouvé le livre très intéressant et très complet. J'ai compris beaucoup de choses vu ici et là dans des bouts de code python. Autant "Apprendre à programmer en python m'avait permis d'appréhender python et son modèle objet mais sans forcément me donner toutes les clés, autant là, j'ai l'impression d'avoir une bonne bible sous la main et d'avoir fait un grand pas (quitte à avoir trop de clés dans ma besace ;-) ).

A sa décharge et au vu de mon niveau actuel en python, y a des pans du livre qui me sont passés au dessus de la tête / que j'ai survolé, estimant que j'y reviendrais surement plus tard.

Autre petit point négatif mais inhérant à sa date de publication, c'est qu'il ne couvre que la version 2.4 de Python.Sur ce point précis, j'avais hésité avec l'achat de "Au coeur de Python" (Tome 1 et Tome 2) qui couvre python 2.5. Toutefois, en parcourant ce dernier livre, j'ai eu l'impression de parcourir un peu la documentation à la php.net où on assiste à un listing exhaustif des fonctions disponibles mais sans plus. Je trouve "Programmation Python" pour le coup plus pédagogique et mieux enrobé quitte pour certains points à ne donner que l'essentiel (et un peu plus) et des pointeurs si nécessaire.

Pour finir sur un point positif, l'aspect méthodologie (test, doctest, design pattern, etc) est très bien documentée et sera complétée dans le livre Petit guide à l'usage du développeur agile.

Bref, un livre à lire tant pour des débutants (qui se focaliseront sur la première partie du livre) ou des développeurs plus expérimentés qui se focaliseront sur la seconde partie.

Il me reste juste à trouver un éditeur de code python qui me va bien pour aller plus loin... (je veux un textmate-like pour Linux)

mardi 19 février 2008

SPE (Stani's Python Editor) 0.8.4.c dispo sous Archlinux

Archlinux disposant d'une fort vieille version de SPE, je me suis décidé à mettre à jour le fichier PKGBUILD existant en partant de ce qui existait originellement et aussi du paquet spe-svn (paquet orphelin, tout comme spe jusqu'à ce soir).

Cela donne donc SPE 0.8.4.c pour Archlinux.

Pour l'installer :

yaourt -S spe

Par contre, sous Debian Testing, spe ne fonctionne pas suite à un problème de dépendances sur wxpython :-(

vendredi 18 janvier 2008

Lecture : The Definitive Guide to Django: Web Development Done Right

Je viens de terminer la lecture du livre "The Definitive Guide to Django: Web Development Done Right",écrit par les développeurs principaux du framework python Django, à savoir Jacob Kaplan-Moss et Adrian Holovaty.

Le livre est décomposé en trois grandes parties :

  • Partie 1 : Présentation de l'outil
  • Partie 2 : Dans les entrailles de Django : présentation des modules et "sous-frameworks"
  • Partie 3 : Annexes avec des témoignages et de la documentation

On peut dire qu'à l'issue de la partie 1, vous êtes en mesure de jouer avec Django pour construire une application de démo, simple et sans prétention. A l'issue de la partie 2, vous l'avez bien enrichit et même déployer en production. Si vous avez réussi à intégrer/mémoriser la partie 3, vous êtes un expert Django ;-)

Ce que j'ai bien aimé :

  • Le livre se veut plus un guide qu'une documentation : le livre ne va pas présenter dans le détail tous les aspects de Django. Il va en présenter suffisamment pour s'en faire une idée, voir l'intérêt de tel ou tel module mais pas détailler l'option X du module Y. La documentation de référence reste celle en ligne et du coup, ils sont à voir comme étant complémentaires et non comme une version papier de la documentation officielle.
  • De nombreuses "bonnes pratiques" tant au niveau de Django que du développement web en général sont données au fur et à mesure du livre. J'ai plié un gros nombre de pages pour me rappeler d'intégrer plein de petits trucs dans mes projets actuels.
  • Si on connait rien en python, les auteurs fournissent suffisamment d'information pour comprendre la logique de l'ensemble. Globalement je trouve le livre très pédagogique.
  • J'ai appris plein de choses que je n'avais pas vu en parcourant la documentation officielle.

Ce que j'ai moins aimé :

  • La partie déploiement est un peu légère à mon goût, je m'attendais à un truc un peu plus solide - pour le coup, c'est pas top évident de déployer une appli django la première fois - surtout quand on vient des applis PHP qui sont "upload & play".

Même si certains choses du livre ont un peu bougé, je pense que ça vaut le coup de l'acheter si on veut se familiariser avec Django. Le livre est également lisible en ligne sur le site djangobook.com. Il paraitrait même que des gens ont proposé de le traduire en français :-)

mardi 11 décembre 2007

Djangoseries du moment

Y a eu pas mal de choses d'intéressant ces derniers temps sur Django, c'était un "morceau choisi". Tout le reste est sur mon tag "django" sur del.icio.us...

vendredi 30 novembre 2007

Django : activer l'autocomplétion dans votre console

Utilisant la version de développement (svn) de Django, j'ai farfouillé dans le contenu du répertoire extras de django et on y trouve un symathique fichier django_bash_completion.

Il vous suffit de placer ce fichier dans /etc/bash_completion.d/ (ou de faire un lien symbolique, ce qui peut être pratique si le fichier est mis à jour et si vous suivez régulièrement la version de développement).

Pour profiter de cette complétion suivant votre distribution GNU/Linux et où l'autocomplétion est définie :

source /etc/profile
 
et/ou :
 
source ~/.bashrc

Ensuite, à la racine de votre projet django, faites :

python manage.py [Tab] [Tab]

et toutes les options possibles vont apparaître :

$ python manage.py
adminindex        loaddata          sqlclear          startproject
createcachetable  reset             sqlcustom         syncdb
dbshell           runfcgi           sqlflush          test
diffsettings      runserver         sqlindexes        validate
dumpdata          shell             sqlreset
flush             sql               sqlsequencereset
inspectdb         sqlall            startapp

Toujours ça de pris :-)

dimanche 18 novembre 2007

Pygments et ReST (partie 2 sur je-sais-pas-combien-encore)

Suite de mon aventure sur Pygments et ReST :

En lisant la documentation rapide (QuickStart) de Pygments, on trouve comment récupérer la feuille de style fournit par défaut :

pygmentize -S default -f html > style.css

Ensuite, lors de la transformation Rest vers HTML, il suffit de faire :

rst2html.py source.txt cible.html --stylesheet-path=style.css

Il y a surement plus propre mais bon, ça marche... Cela veut aussi et surtout dire que pour produire un site à partir de document s au format ReST, il faut construire sa feuille de style CSS en incluant celle de pygments notamment.

Et voilà le résultat :

ReST et Pygments

Voir la capture d'écran

Pygments et ReST (partie 1 sur je-sais-pas-combien-encore)

Dans le monde python, il y a :

  • Une syntaxe de documentation puissante mais pas aisée à prendre en main : ReST, pour ReStructured Text, fourni via docutils. Voir la QuickRef de ReST.
  • Pygments, un système de coloration syntaxique, un peu comme GeSHi en PHP.

Dans vos documents rédigés en ReST, il est possible d'inclure Pygments pour enrichir le rendu de vos documents.

Il vous faut pour cela :

  • docutils installé sur votre ordinateur,
  • pygments aussi
  • récupéré le fichier external/rst-directive.py présent dans le fichier source de pygments 0.9 et le copier dans /usr/lib/python2.5/site-packages/docutils/parsers/rst/directives/

Ensuite, et c'est là où le système manque un peu de flexibilité, il faut déclarer cette directive :

  • Editer /usr/lib/python2.5/site-packages/docutils/parsers/rst/directives/init.py (il y a deux "_" de chaque coté du init - bug de DC2 apparemment) pour ajouter une ligne :
_directive_registry = {
      'sourcecode': ('rst-directive', 'pygments_directive'),
      'attention': ('admonitions', 'Attention'),
      ...
      }

Cette déclaration dit que quand j'utiliserais la directive sourcecode dans mon document ReST, alors il doit aller utiliser la classe pygments_directive présente dans le fichier rst-directive.py.

  • Editer le fichier /usr/lib/python2.5/site-packages/docutils/parsers/rst/languages/en.py (et les éventuelles traductions) :
directives = {
      # language-dependent: fixed
      'sourcecode': 'sourcecode',
      'attention': 'attention',
      ...
      }

Voilà pour l'installation de pygments et docutils.

Dans votre texte au format ReST, il vous suffit d'utiliser la directive sourcecode comme dans l'exemple suivant :

Tutoriel : partie 1
===================

settings.py
-----------

.. sourcecode:: python

    # Django settings for tutoriel project.

    DEBUG = True
    TEMPLATE_DEBUG = DEBUG

    ADMINS = (
        # ('Your Name', 'your_email@domain.com'),
    )

Si vous voulez que les numéros de lignes soient également mentionnés, il vous faut décommenter la ligne suivante (dans rst-directives.py) :

et modifier votre fichier de la façon suivante (ajout de la directive :linenos: :

Tutoriel : partie 1
===================

settings.py
-----------

.. sourcecode:: python
    :linenos:

    # Django settings for tutoriel project.

    DEBUG = True
    TEMPLATE_DEBUG = DEBUG

    ADMINS = (
        # ('Your Name', 'your_email@domain.com'),
    )

Je vous fais grâce du code html de rendu, surtout que pour le moment, je n'ai pas de coloration syntaxique (cf Pygments et ReST Partie 2)

jeudi 15 novembre 2007

Django : internationaliser vos modèles dans vos applications

La documentation sur l'internationalisation d'une application Django m'ayant laissé perplexe tant en anglais qu'en français, voici un petit résumé de ce qu'il faut faire.

Dans settings.py, il vous faut :

  • Avoir un language code correctement configuré
  • Que USE_I18N soit bien activé - c'est le cas par défaut
  • Ajouter 'django.middleware.locale.LocaleMiddleware', à la liste de vos middleware. Attention l'ordre compte - cf documentation

Exemple :

[...]
 
LANGUAGE_CODE = 'fr'
 
USE_I18N = True
 
[...]
 
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.doc.XViewMiddleware',
)
 
[...]

Dans app/models.py :

  • Importer gettext_lazy fourni par django. gettext_lazy() s'utlise pour traduire les champs des modèles
  • Pour éviter d'écrire gettext_lazy('Single'), on peut utiliser le système d'alias pour n'écrire que : _('Single') .
  • Si vous êtes en unicode, c'est ugettext_lazy() et non gettext_lazy() bien sûr,

Exemple :

# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
 
"""
Profile
 
This object is used to provide some common information regarding the profile of a user.
"""
 
class Profile(models.Model):
    CIVILITY_CHOICES = (
         ('single', _('Single')),
         ('taken', _('Taken')),
    )
    who = models.ForeignKey(User, unique=True, verbose_name=_('Person'),)
    photo = models.ImageField(height_field="80", width_field="80", upload_to="photos", blank=True)
    street = models.CharField(_('Address 1'), maxlength=100)
    street_bis = models.CharField(_('Address 2'), maxlength=100, blank=True)
    zipcode = models.IntegerField(_('Zip code'), maxlength=5)
    city = models.CharField(_('City'), maxlength=100)
    phone = models.CharField(_('Phone'), maxlength=20)
    mobile = models.CharField(_('Mobile'), maxlength=20, blank=True)
    civility = models.CharField(_('Status'), maxlength=20, choices=CIVILITY_CHOICES)
    birthdate = models.DateField(_('Birth date'))
    children = models.IntegerField(_('Children'), blank=True, null=True)

Dans le répertoire de votre application, créer un répertoire "locale" :

mkdir -p /chemin/de/votre/projet/django/app/locale

Ensuite il vous faut générer votre fichier de langue .po correspondant à votre langue (ici : fr):

/usr/lib/python2.5/site-packages/django/bin/make-messages -l fr

Saisissez alors la traduction dans app/locale/<langue>/LC_MESSAGES/django.po

Exemple :

#: models.py:14
msgid "Single"
msgstr "Célibataire"

Compiler ensuite votre fichier de langue :

/usr/lib/python2.5/site-packages/django/bin/compile-messages

Vous obtenez alors un fichier app/locale/<langue>/LC_MESSAGES/django.mo

Dans votre template :

  • ajouter {% load i18n %} en tête de template

Ex :

{% extends "base.html" %}
{% load markup %}
{% load i18n %}

Si vous utilisez le serveur de développement, il faut le redémarrer pour qu'il prenne en compte les fichiers de langue compilés (idem lors d'une mise à jour des fichiers de langue).

Et voilà, savourez le travail...

Merci à benoitc et anhj de #django-fr pour m'avoir aidé à trouver mon erreur (ie avoir créer dans le répertoire de mon application une structure conf/locale au lieu de locale. La première ne s'utilise que pour l'ensemble d'un projet django).

dimanche 16 septembre 2007

Django : utilisation de regroup avec tri sur des clés étrangères

Objectif : Utilise la balise "regroup" en filtrant sur une clé étrangère

Modèle :

Soit le modèle suivant :

"""
Technicat skills
"""
 
class DomainTechSkill(models.Model):
     name = models.CharField('Domaine de compétence technique', Maxlength=100, core=True)
 
class Techskill(models.Model):
     who = models.ForeignKey(User, verbose_name='Personne',)
     name = models.CharField('Compétences techniques', maxlength=100, core=True)
     domain = models.ForeignKey(DomainTechSkill, verbose_name='Domaine de compétences techniques',)
 
class Usertechskill(models.Model):
     who = models.ForeignKey(User, verbose_name='Personne',)
     name = models.ManyToManyField(Techskill, verbose_name='Compétence technique', filter_interface=models.HORIZONTAL, blank=True)

L'idée est de faire d'une part TechSkill <=>DomainTechSkill et d'autre part User <=> TechSkill. Ensuite au niveau de la restitution, on veut lister les compétences techniques d'un utilisateur en les regroupant par "DomainTechSkill".

Vue :

avec la vue suivante (extrait) :

def cv_detail(request, firstname, lastname):
     user = User.objects.get(first_name=firstname, last_name=lastname)
     user_techskill = user.usertechskill_set.all()
     return render_to_response('cv/cv_detail.html', {'user_techskill': user_techskill, })

Template :

et le template suivant (extrait) :

                 {# -- technical skills -- #}
                 {% if user_techskill %}
                 <p>Comp&eacute;tences techniques :</p>
                 {% for techskill in user_techskill %}
                 {% regroup techskill.name.all|dictsort:"domain" by domain as grouped %}
                 <ul>
                          {% for group in grouped %}
                                 <li> {{ group.grouper }} :
                                         {% for item in group.list %}
                                                 {{ item.name }}{% if forloop.last %}.{% else %},{% endif %}
                                         {% endfor %}
                                 </li>
                          {% endfor %}
                 </ul>
                 {% endfor %}
                 {% endif %}

Jeux de données :

Imaginons que j'ai alors rentré les couples de valeur suivants (Compétence techniques / Domaine Technique) :

  • HTML / Web
  • CSS / Web
  • Apache / Serveur
  • Portail / Système d'information
  • Bind / Serveur
  • CMS / Système d'information

Ce qui est souhaité :

  • Serveur : Apache, Bind
  • Système d'information : CMS, Portail
  • Web : HTML, CSS

Ce qui est parfois obtenu (comme n'importe quelle autre combinaison de ces valeurs, ce qui nous permet d'avoir la bonne de temps à autre)

  • Serveur : Apache
  • Système d'information : CMS, Portail
  • Serveur : Bind
  • Web : HTML, CSS

Solution pour avoir la bonne combinaison de façon systématique :

La solution consiste dès lors à ajouter le nom de l'attribut (ex : domain.name) ou de filtrer par un id (ex : domain.id)

                 {% regroup techskill.name.all|dictsort:"domain.name" by domain as grouped %}

Et là, vous avez systématiquement le résultat souhaité (seul l'ordre des compétences peut varier sur une même ligne)

Merci à Samuel pour m'avoir indiqué cette capacité.

samedi 15 septembre 2007

Django et les fixtures

Sauvegarder les données saisies dans une instance sous la forme de fixture :

Pour sauver toutes les données de votre projet :

python manage.py dumpdata --indent=4 > initial_data.json

Note :

  • le --indent=4 permet que le fichier créé soit correctement indenté et plus facile à lire.
  • par défaut, c'est exporté au format json
  • en nommant votre fichier initial_data.* il sera chargé automatiquement par django lors d'un syncdb, reste ou sqlreset

Pour sauver les données d'une application nommée "monapp" :

python manage.py dumpdata --indent=4 monapp > initial_data.json

Attention, si vous voulez opérer un changement sur votre modèle, il faut faire le dump avant de faire des modifications, sinon cela ne marche pas.

Pour charger une fixture, il suffit de faire :

python manage.py loadata ma_fixture.json

Passer de sqlite à MySQL (ou autre) en ayant des caractères accentués :

Lors du passage de Sqlite à MySQL, j'ai eu le bug suivant avec les exports en json : tous mes caractères accentués étaient transformés en caractères spéciaux. Le seul moyen fut de passer par un export xml :

python manage.py dumpdata --format=xml --indent=4 monapp > initial_data.xml

- page 2 de 4 -