title: Ajout des flux RSS, du sitemap et des commentaires avec Django slug: ajout-des-flux-rss-du-sitemap-et-des-commentaires-avec-django date: 2007-06-23 19:21:39 type: post vignette: images/logos/biologeek.png contextual_title1: Biologeek (enfin) propulsé par Django contextual_url1: 20080423-biologeek-enfin-propulse-par-django contextual_title2: De Dotclear à Django : migration des données et redirections contextual_url2: 20070523-de-dotclear-a-django-migration-des-donnees-et-redirections contextual_title3: Vues génériques, héritage et templatetags : développez rapidement avec Django contextual_url3: 20070424-vues-generiques-heritage-et-templatetags-developpez-rapidement-avec-django
Suite de la refonte de ce blog qui commence vraiment à trainer en longueur... il faut dire que ça me prend souvent plus de temps de décrire ce qui est fait que de le coder ! Du coup c'est probablement le dernier billet à ce sujet. De toute façon c'est presque terminé, il ne me reste plus qu'à mettre quelques surprises et à adapter le thème, voire peut-être à tenter un Cascading Style Summer Refresh 2007 mais j'en doute car je vais manquer de temps ces prochains mois.
J'essaye toujours d'utiliser au maximum les fonctionnalités offertes par Django qui suit la philosophie Python « batteries incluses ». Dans le cas des flux je voulais quelque chose de très spécifique donc il a fallu mettre un peu les mains dans le cambouis mais c'est ce qui fait le charme d'un framework : on peut tout contrôler !
On commence par le cahier des charges, le but était d'avoir des URL du type /abonnement/{ rss, atom }/{journal, bistrot, tag, liste de tags }/ afin de laisser la possibilité d'utiliser soit RSS, soit Atom tout en ayant des URL relativement courtes et compréhensibles. Au niveau du fichier des URL on retrouve donc :
from biologeek.feeds import RSSFeed, AtomFeed urlpatterns += patterns('django.contrib.syndication.views', (r'^abonnement/(?P<url>.*)/$', 'feed', {'feed_dict': { 'rss': RSSFeed, 'atom': AtomFeed }} ), )
Les clés du dictionnaire feed_dict vont être passées en paramètre de la fonction feed pour se retrouver dans l'URL donc jusqu'ici on a /abonnement/{ rss, atom }/. C'est ensuite au niveau des classes RSSFeed et AtomFeed qu'il faut décider du contenu qui va être proposé :
from django.contrib.syndication.feeds import Feed from biologeek.journal.models import Post class RSSFeed(Feed): description = u'Dernières mises à jour du site de David Larlet : biologeek.com relatives aux %s' author_name = 'David Larlet' author_link = 'http://larlet.fr/' copyright = 'Copyright (c) 2004-2007, David Larlet, Licence Art Libre' def get_object(self, bits): if len(bits) == 1: bit = bits[0] if bit == 'journal': self.title = 'Flux RSS des billets du journal du site biologeek.com' self.link = '/journal/' self.description = self.description % u'billets du journal' return Post.published.all()[:25] [...] else: raise ObjectDoesNotExist def items(self, obj): return obj
Je ne mets pas tout mais vous aurez compris le principe (si non vous pouvez récupérer les sources sur le dépôt). En fonction de la valeur passée en URL, un contenu approprié est proposé. C'est pas vraiment élégant et cela tient au cahier des charges un peu spécial que je m'étais fixé, sinon c'est beaucoup plus simple comme vous pouvez le voir dans la documentation.
Lorsque l'on veut passer au flux Atom, il suffit d'hériter de la classe utilisée pour le RSS :
from django.utils.feedgenerator import Atom1Feed class AtomFeed(RSSFeed): feed_type = Atom1Feed subtitle = RSSFeed.description
Un sitemap est une aide pour les moteurs de recherche. C'est un fichier xml permettant d'indiquer l'importance relative des pages du site et leur fréquence de mise à jour. Il est généralement placé sur /sitemap.xml et il est nécessaire de le déclarer pour qu'il soit indexé. On va ici se servir du module sitemap de Django, on rajoute donc l'URL :
from biologeek.sitemaps import sitemaps urlpatterns += patterns('django.contrib.sitemaps.views', (r'^sitemap.xml$', 'sitemap', {'sitemaps': sitemaps}) )
La gestion des sitemaps peut se faire de manière générique, ce qui est très pratique pour les modèles que j'ai choisi :
from django.contrib.sitemaps import GenericSitemap from biologeek.journal.models import Post sitemaps = { 'journal_bestof': GenericSitemap( { 'queryset': Post.published.filter(is_bestof=True), 'date_field': 'publication_date' }, priority=0.6 ), 'journal': GenericSitemap( { 'queryset': Post.published.exclude(is_bestof=False), 'date_field': 'publication_date' }, priority=0.4 ), [...] }
Par contre j'ai pas mal cherché pour arriver à rajouter les liens qui ne sont pas inhérents à des modèles comme l'accueil ou les pages d'agrégation de ressources. J'ai finalement créé une classe dédiée à ça :
from django.contrib.sitemaps import Sitemap class BaseSitemap(Sitemap): priority = 0.8 def items(self): return ['/', '/journal/', '/bistrot/', '/archives/', '/abonnement/', '/contact/'] def location(self, obj): return obj
qu'il suffit ensuite d'ajouter au dictionnaire précédent. Comme vous pouvez le remarquer, je ne spécifie pas la fréquence de mise à jour car les pages de ressources sont susceptibles d'évoluer au cours du temps grâce aux commentaires et celles d'agrégations sont mises à jour de façon non régulière compte tenu de mon rythme de publication. Dans le doute, il vaut mieux s'abstenir Google saura mieux algorithmer tout ça que vous.
Comme je le disais plus haut j'aime bien utiliser les modules déjà inclus dans Django. Pour les commentaires, je vais peut-être faire une petite exception pour deux raisons :
Je n'ai pas encore décidé de ce que j'allais faire. Il me reste aussi à intégrer l'identification via OpenID pour vous rendre la vie plus facile :-).
Prochaine étape... euh... la mise en ligne ! J'ai pas mal galéré pour Django-fr donc ça devrait aller beaucoup plus vite.