Journal Retour d'expérience sur la mise en ligne d'un nouveau site (Django)

Posté par (page perso) . Licence CC by-sa
22
22
déc.
2013

Sommaire

Intro

Une part de mon temps libre, je le passe à Radio Panik, une des radios libres de Bruxelles, pas seulement pour y faire de l'informatique même si c'est par là que je suis entré, et que ça reste une part importante et intéressante à plus d'un titre (environnement en logiciels libres, parc d'une dizaine de postes clients (Debian/GNOME) et de quelques serveurs (Debian aussi), développements spécifiques, touchant parfois à l'électronique, etc.). (d'ailleurs si ça vous tente l'équipe est ouverte)

C'est dans ce cadre que la semaine dernière, on a mis en ligne un nouveau site web, passant d'un site Spip qui avait petit à petit évolué depuis une version utilisant encore PHP3 à un site entièrement développé par nos petites mains, en utilisant Django. Après plus d'un an de travail, il me semble qu'il y a quelques points sur lesquels un retour public peut être intéressant.

C'est un travail d'équipe (cf la page "crédits" du site) et il y a des trucs sur lesquels revenir dans tous les aspects (des rencontres initiales avec des membres de la radio et auditeurs pour définir une direction à tout un travail graphique ou sur le "responsive design") mais je vais me limiter à ce qui m'a concerné tout particulièrement.

Migration des données (syntaxe SPIP mon amour)

Pour le contexte technique, il est important de savoir qu'on partait d'un site Spip relativement chargé (près de 5000 articles, des centaines de rubriques, un tas de fichiers attachés pour les podcasts), qu'il fallait conserver toutes ces informations, mais qu'en même temps on avait des envies qui dépassaient Spip (d'après nous, nos connaissances et nos envies).

Le premier point ça a du coup été de valider qu'on pouvait de manière automatique convertir le contenu vers un modèle plus structuré, et ce fut vite fait, le module de "dump XML" de Spip fournit quelque chose d'assez lisible (et de presque valide, un module externe introduisant des données dans un mauvais encodage) et même si on partait de ce qui n'étaient que rubriques et articles, la hiérarchie du site amenait une heureuse structure.

J'ai aussi la chance d'avoir participé il y a quelques années à un projet qui comportait un parseur de "syntaxe Spip" écrit en Python, que j'ai retrouvé pour l'occasion et rendu un petit peu plus indépendant. Cela étant Spip n'impose pas une pratique scrupuleuse de sa syntaxe et vit très bien avec un gloubi boulga de spip et d'HTML, et les rédacteurs ne s'étaient pas privés de profiter de cela (allant de quelques balises HTML perdues au milieu du tout, à des articles entiers créés par copié/collé depuis un éditeur HTML). Même si un important travail a été fait pour également traité ça de manière correcte, il reste encore de parts et d'autres des textes où des balises HTML n'ont pas été interprétées correctement, et converties en <foo> et autres.

Plusieurs fois je me suis dit que ça vaudrait la peine d'en rester au PHP pour cette partie et de faire directement appel au code de Spip pour cette partie, mais je n'ai pas trouvé (assez rapidement) comment extraire ça proprement du code de Spip.

Architecture technique (d'un PostgreSQL à l'autre)

Pour établir nos certitudes sur l'import des données de Spip en place, un début de backoffice s'était mis en place, permettant de naviguer dans les données importées, et il semblait logique de l'étendre pour en faire l'interface de gestion à laquelle les animateurs auraient accès, mais pour ce qui concernait le site web à proprement dire, les pistes étaient moins claires.

Il faut noter que le backoffice était prévu pour tourner sur un des serveurs hébergés à la radio, pour permettre aux personnes sur place de rapidement y mettre des sons, sans devoir attendre le lent upload de ceux-ci par la connexion asymétrique.

On se trouvait donc d'un côté avec toutes les données pour faire un site, au milieu une connexion ADSL, et de l'autre côté un serveur web. Comme on était pas loin d'un temps où CrEv parlait de tout, de rien, de bookmarks, de bla bla et de comment faire une page web de nos jours, on se disait quand même qu'un système comme Hyde ou Jekyll ne serait pas mal du tout, et offrirait une solution des plus simples.

Mais finalement comme on était déjà bien dans Django, qu'on avait un tas de code déjà présent dans le backoffice et qui ne demandait qu'à être réutilisé, on a finalement opté pour simplement avoir un autre projet Django pour le site web (et du coup de devoir quitter l'espace web qu'on occupait, sur lequel il n'était pas possible d'installer tout ce dont on allait avoir besoin).

Pour la synchronisation des données d'un site à l'autre, outre un rsync régulier pour les fichiers, on a regardé à ce qu'on pouvait faire directement avec PostgreSQL et on est tombé sur Bucardo, ça ressemble à du gros bricolage en Perl, ce n'est pas terriblement documenté, mais ça marche très bien.

Et c'est ainsi que le tour fut joué, deux bases de données partageant une série de tables, et du backoffice vers le site web la synchro des tables communes.

Déploiement (de tout, de rien, des liens)

Tant qu'à parler du déploiement effectif, il faut noter que le projet Django publie désormais une checklist bien utile.

À côté des pratiques notées là-dedans, il y a un serveur memcached pour le cache (pages et templates), un serveur sentry pour le suivi des erreurs et un serveur graphite pour le suivi des performances (via django-statsd-mozilla] (découvert via le blog webdev de Mozilla).

Et parce qu'un nouveau site ne doit pas signifier des tonnes de 404, mais que les anciennes URIs n'étaient pas "cool" (commençant par /spip/), il y a une grande table de correspondance mise en place via RewriteMap.

Performances (big up à Solr)

Comme on peut suivre les performances des pages, on peut se rendre compte de celles où ce n'est pas terrible, puis creuser et voir les trucs à améliorer; et là il y a encore des choses à faire (même si le premier truc ça pourrait être d'être hébergé sur plus véloce qu'un Atom d'un kimsufi).

La cible du moment, c'est les relations Many-to-Many (qu'on utilise pour ranger une émission dans plusieurs catégories), elles sont dans nos usages vraiment coûteuses, on doit réfléchir à l'utilisation du type Array présent dans PostgreSQL mais sans casser le fonctionnement avec SQLite pratique pour les développements en local, et sans s'éloigner trop de l'ORM de Django.

Par contre, une des bonnes confirmations de ce projet, ça a été Solr, ça poutre vraiment et le MoreLikeThis est très chouette pour inviter à visiter des contenus proches. En plus il y a une excellente intégration dans Django grâce à Haystack.

Pour conclure (+ question + bonus)

J'ai touché ici à des aspects sur lesquels on s'est particulièrement interrogés, et qu'il me semblait utile à exposer et éventuellement discuter, mais pour les curieux/ses, le code complet est disponible en bas de la page Crédits.

Après tout ça, une grande interrogation reste la gestion des pages de contenus non structurés (par exemple si le conseil d'administration veut publier un HOWTO gérer un budget), pour le moment les quelques pages sont gérées via Fiber mais on sent déjà que ça ne tiendra pas la route, si vous avez des idées (ou des retours sur Django-CMS), ça nous intéresse.

Pour vraiment finir, en bonus, dans les petits trucs que j'ai appris, si jamais vous devez afficher des vignettes dans un aspect-ratio différent de l'original, si l'image d'origine est en portrait, le résultat est bien meilleur en visant le haut de l'image que le milieu. code

  • # Déploiement de Django

    Posté par (page perso) . Évalué à 5.

    Perso, je trouve que le déploiement reste le point faible de Django, à cause de son fichu fichier settings.py, qui contient à la fois du code et des paramètres. Je trouve dommage que Django propose par défaut une solution assez sale :(

    Dans deux petits projets récents pour chez moi (un clone de Pypi et un site d'upload de documentations), j'ai un peu contourné la chose avec un settings.py qui va lire un fichier de conf pour quelques paramètres à changer, ce qui me permet de faire un pip install mon_projet --upgrade (ce qui est quand même plus propre à mes yeux). Par contre, c'est plus difficile quand on a un settings.py avec pas mal de paramètres…

    Je suis également en train de bosser sur un projet de migration de site, mais je passe d'un projet Django à un autre, alors la migration est plus simple, je bosse sur un code d'importation automatique qui utilise massivement l'introspection Python.

    Sinon, la question qui fâche : Python 2 ou 3 ? :D

    • [^] # Re: Déploiement de Django

      Posté par . Évalué à -1.

      Aurais-tu un exemple d'usage de l'introspéction? J'ai du mal à envoir le besoin et l'apport.

      merci

      • [^] # Re: Déploiement de Django

        Posté par (page perso) . Évalué à 3.

        Pour faire rapidement :
        j'ai deux applications Django qui se ressemblent pas mal, avec chacune beaucoup de modèles (autour de la centaine).
        Je veux réimporter les données de l'une dans l'autre, mais je ne veux pas établir à la main la correspondance entre les modèles car ça serait trop pénible et source d'erreurs.
        Sachant qu'avec quelques règles simples du genre « les classes finissant par *X sont renommées en *Y », « tel attribut est renommé en truc », « tel nouvel attribut est la fusion de ces deux vieux attributs » , « les modèles avec deux clefs ForeignKey sont repris par des ManyToManyFields », etc, j'arrive à cerner 99% des modifications…
        J'arrive donc à programmer la correspondance des classes et des attributs en faisant de l'introspection pour les déterminer, pour faire une passe à la main pour corriger les erreurs restantes.

        Autre souci, j'ai plusieurs classes qui ont des dépendances réciproques. Dans ce cas, je peux déterminer automatiquement l'ordre de création des objets (la relation qui peut être vide n'est pas prise en compte lors d'une première passe).

        Puis au passage, je génère un graphe régulièrement, afin de déterminer les relations entre classes, en mettant en valeur les classes qui héritent d'une classe particulière, ainsi que celles dont la partie admin est faite (idem pour les relations).

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.