title: Initialisation et modèles de données de la refonte slug: initialisation-et-modeles-de-donnees-de-la-refonte date: 2007-04-12 07:38:11 type: post vignette: images/logos/biologeek.png contextual_title1: Biologeek (enfin) propulsé par Django contextual_url1: 20080423-biologeek-enfin-propulse-par-django contextual_title2: Ajout des flux RSS, du sitemap et des commentaires avec Django contextual_url2: 20070623-ajout-des-flux-rss-du-sitemap-et-des-commentaires-avec-django contextual_title3: De Dotclear à Django : migration des données et redirections contextual_url3: 20070523-de-dotclear-a-django-migration-des-donnees-et-redirections
Suite de la refonte de ce blog, qui a pris un peu de retard. Aujourd'hui on va de l'initialisation de l'environnement de développement au modèle de données retenu. Je pars vraiment de la base pour que vous puissiez réellement suivre la refonte si vous êtes intéressé(e). C'est d'ailleurs la raison pour laquelle j'ai mis le code sur un dépôt public (cf. fin du billet).
Commençons par installer django, j'ai décidé de mettre les sources dans ~/web/ car j'avais l'habitude d'avoir la dernière version à jour et c'est quand même plus pratique d'être dans sa home pour faire un svn up. Depuis la sortie de la 0.96, la version du dépôt officiel n'est plus aussi stable qu'avant (comme il était prévu), nous allons donc installer la version 0.96 pour la refonte :
$ cd & cd web $ wget http://www.djangoproject.com/download/0.96/tarball/ $ tar xvf Django-0.96.tar.gz && rm Django-0.96.tar.gz $ sudo ln -sf /home/david/web/Django-0.96/django /usr/lib/python2.5/site-packages/
À adapter bien entendu à votre configuration (python 2.5 par défaut avec Feisty \o/). Normalement la commande ls -l /usr/lib/python2.5/site-packages/dj* devrait vous renvoyer :
lrwxrwxrwx 1 root root 34 2007-04-02 08:32 /usr/lib/python2.5/site-packages/django -> /home/david/web/Django-0.96/django
Vous pouvez aussi vérifier en faisant un python -c "import django;print django.VERSION" qui ne devrait pas lever d'erreur et renvoyer (0, 96, None). Si vous récupérez directement les sources du projet, les étapes d'initialisation suivantes sont inutiles.
Ok, tout marche bien, créons donc notre projet de refonte (par commodité, je me mets dans le dossier refonte) :
$ mkdir refonte && cd refonte $ /usr/lib/python2.5/site-packages/django/bin/django-admin.py startproject biologeek $ cd biologeek/
Vous pouvez aussi mettre le répertoire bin de django dans votre $PATH pour ne pas avoir à aller le récupérer dans les paquets python mais comme je ne m'en sers que pour la création de projets je trouve ça un peu inutile.
Il ne reste plus qu'à paramétrer tout ça en modifiant le fichier settings.py et vous pourrez alors synchroniser la base pour la première fois :
$ python manage.py syncdb
La création d'un super-utilisateur est demandée, une fois cet utilisateur créé, vous pouvez lancer votre serveur de développement pour la première fois :
$ python manage.py runserver
En vous rendant sur http://127.0.0.1:8000/ vous aurez le message de bienvenue et sur /admin/ vous pourrez accéder à votre interface d'administration (en décommentant la ligne dans urls.py).
On va maintenant créer les deux « applications » de la refonte : journal et bistrot.
$ python manage.py startapp journal $ python manage.py startapp bistrot
Je m'arrête là pour l'initiation à Django, ces bases là suffisent pour comprendre ce qui va suivre, si vous voulez en savoir plus rien ne vaut un bon tutoriel.
Le modèle de données doit être placé dans les fichiers models.py situés dans les répertoires des deux applications créées. Le journal va contenir des billets qui auront le modèle suivant :
class Post(models.Model): title = models.CharField('Titre', maxlength=200) slug = models.SlugField('Adresse', prepopulate_from=('title',), primary_key='True') tags = models.ManyToManyField(Tag, help_text='Sélectionnez les tags.') summary = models.TextField('Description', help_text='Différentes syntaxes possibles (cf. markup)', blank=True) summary_html = models.TextField('Description HTML', blank=True) content = models.TextField('Contenu', help_text='Difféntes syntaxes possibles (cf. markup)') content_html = models.TextField('Contenu HTML', blank=True) related_posts = models.ManyToManyField('self', help_text='Sélectionnez les billets en relation.', blank=True) related = models.TextField('Contenu additionnel', help_text='Difféntes syntaxes possibles (cf. markup)', blank=True) related_html = models.TextField('Contenu additionnel HTML', blank=True) creation_date = models.DateTimeField('Date de création') modification_date = models.DateTimeField('Date de modification') publication_date = models.DateTimeField('Date de publication', null=True, blank=True) image = models.ImageField('Image associée', upload_to='%s/media/logos/' % settings.PROJECT_PATH, blank=True) is_draft = models.BooleanField('Brouillon', default=True) is_bestof = models.BooleanField('Best of', default=False) markup = models.CharField(maxlength=20, choices=MARKUP_CHOICES, radio_admin=True, default='markdown')
Je ne vais pas détailler, les champs parlent d'eux-même. Par contre, il est intéressant de commenter le manager que j'ai associé :
class PostManager(models.Manager): def get_query_set(self): """ Retrieve only published posts. """ qs = super(PostManager, self).get_query_set() return qs.filter(is_draft=False) def get_best_of(self): """ Retrieve only best of published posts. """ qs = super(PostManager, self).get_query_set() return qs.filter(is_bestof=True)
Un manager permet d'accéder facilement à un catégorie de billets, il faut pour cela ajouter à votre classe Post par exemple :
class Post(models.Model): [...] objects = models.Manager() published = PostManager()
Et la récupération des données est simplifiée ainsi :
On peut faire beaucoup de choses avec les managers et c'est relativement pratique pour ne pas se tromper lorsque l'on doit continuellement filtrer des données à accès restreint.
Pour les brèves du bistrot, le code est assez similaire :
class Thought(models.Model): title = models.CharField('Titre', maxlength=200) slug = models.SlugField('Adresse', prepopulate_from=('title',)) tags = models.ManyToManyField(Tag, help_text='Sélectionnez les tags.') content = models.TextField('Contenu', help_text='Vous pouvez utiliser markdown') content_html = models.TextField('Contenu HTML', blank=True) creation_date = models.DateTimeField('Date de création') modification_date = models.DateTimeField('Date de modification') publication_date = models.DateTimeField('Date de publication', null=True, blank=True)
Il y a juste le manager dans lequel je suis en train d'intégrer les votes donc j'en parlerais probablement plus tard, je vais m'arrêter là sinon je publierais jamais ce billet :-).
J'ai créé pour l'occasion un projet sur Google Code qui contient l'intégralité du code. Vous pouvez facilement récupérer le code avec subversion :
svn checkout http://biologeek.googlecode.com/svn/trunk/ biologeek
Checkoutez, testez, participez !