Générer des documents bureautiques avec Django

Une présentation des outils mis en place par Makina Corpus pour produire des documents LibreOffice, Microsoft Office, PDF, etc. au sein du framework Django.

Le blog Makina-corpus

Une présentation des outils mis en place par Makina Corpus pour produire des documents LibreOffice, Microsoft Office, PDF, etc. au sein du framework Django.

Dans le projet Django Geotrek, nous devions produire des documents bureautiques (Libre/OpenOffice, Microsoft Office, PDF...). Pour cela, nous avons mis au point deux composants :

  • django-appypod, qui fournit des vues avec templates de documents, construit à partir de Appy.pod ;
  • convertit, une Web API générique de conversion de formats.

django-appypod

Appy est un ensemble d'outils (i.e. framework) développé par Gaetan Delannay, qui fournit, entre autres, un moteur de templates en python pour les fichiers OpenDocument.

Un des gros avantages est l'édition des templates directement dans LibreOffice, WYSIWYG !

django-appypod fournit une vue Django qui effectue le rendu d'un template OpenDocument pour un contexte donné. Exactement de la même façon que les pages HTML.

Avec les class-based generic views, ça donne ça:

from django.view.generic.detail import TemplateView

from djappypod.response import OdtTemplateResponse

class YourDocument(TemplateView): response_class = OdtTemplateResponse template_name = "your/template.odt"

def get_context_data(self, **kwargs): kwargs['title'] = 'Simple as hello ;)' return kwargs

Et avec les bonnes vieilles functions-based views :

def your_view(request): context = { 'title': 'Simple as hello ;)' } response = OdtTemplateResponse(request, "your/template.odt", context) response.render() return response


ConvertIt

Nous avons souvent besoin de produire ces même documents au format PDF. Et énormément d'utilisateurs ne se contentent pas des formats OpenDocument.

Appy peut faire appel à OpenOffice en mode serveur pour convertir les documents vers PDF ou MS-Word, mais nous n'aimions pas du tout l'idée de devoir déployer les binaires OpenOffice au sein des projets Django.

Par conséquent, nous avons créé ConvertIt, une Web API qui va simplement se charger de convertir des formats. Le service peut tourner sur un serveur dédié (ou un conteneur), et donc isoler les dépendances nécessaires à la conversion de formats exotiques.

Pour l'instant, nous avons implémenté la plupart des conversions de formats bureautiques (.pdf, .doc, .xls), ainsi que SVG vers PDF et PNG.

Image Docker

Si vous utilisez Docker, vous pouvez faire tourner une instance ConvertIt dans un conteneur en une seule commande :

sudo docker run -p :6543 makinacorpus/convertit

Installation manuelle

Il s'agit d'un projet python/Pyramid, tout ce qu'il y a de plus simple :

pip install convertit

Avec en plus quelques paquets système pour les conversions (chacun est optionel):

sudo apt-get install -y libreoffice unoconv inkscape

Pour lancer une instance de développement :

pserve development.ini --reload

Ou en production, avec gunicorn :

pip install gunicorn gunicorn --paste production.ini

Utilisation

Avec une requête GET :

curl http://convertit/?url=http://server/document.odt&to=application/pdf
HTTP/1.1 302 Found
Content-Disposition: attachement; filename=document.pdf
...

En uploadant un fichier avec POST :

curl -F "file=@tiger.svg" http://convertit/?to=image/png
HTTP/1.1 302 Found
Content-Disposition: attachement; filename=tiger.png
...


Integration avec Django

Si l'accès aux documents ne nécessite pas d'authentification, un template tag simple et stupide qui redirige vers le serveur de conversion fera l'affaire :

from django.conf import settings from django import template from django.core.urlresolvers import reverse, NoReverseMatch

register = template.Library()

@register.simple_tag def convert_url(request, sourceurl, format='application/pdf'): try: sourceurl = reverse(sourceurl) except NoReverseMatch: pass fullurl = request.build_absolute_uri(sourceurl) return "%s?url=%s&to=%s" % (settings.CONVERSION_SERVER, urllib.quote(fullurl), urllib.quote(format))

À placer dans une page par exemple:

<a href="{% convert_url "app:document" object.pk %}">Download PDF version</a>

Mais par contre, si les vues vers les documents bureautiques nécessitent un accés loggué, alors il faut mettre en place une de ces stratégies :

  • Login automatique pour les toutes requêtes provenant du service ConvertIt ;
  • Ajouter une vue proxy qui télécharge le fichier, et effectue la conversion à l'aide d'une requête POST ;
  • Mettre en place un Single-Sign-On ou n'importe quel autre mécanisme de jeton ;
  • Contribuer à ConvertIt pour ajouter le support de l'authentification HTTP (url=http://user:pass@host) ;

J'ai codé la première option à titre d'exemple.


En bref...

  • django-appypod sort du lot grâce aux templates WYSIWYG ;
  • ConvertIt est séduisant pour ses côtés génériques et réutilisables ;
  • Les deux fonctionnent ensemble à merveille et fournissent un ensemble varié de formats bureautiques et PDF ;

Si le PDF vous suffit, notez qu'il y a des alternatives :

Actualités en lien

Image
Django Python Keycloak
18/11/2021

Administrer des comptes Keycloak depuis une application Python/Django

Dans cet article, nous allons créer une application Python/Django qui agira en tant que maître sur Keycloak afin de pouvoir ajouter facilement des comportements personnalisés à Keycloak.

Voir l'article
Image
Geotrek Signalement
29/09/2021

Gestion des territoires naturels : Geotrek intègre l’écosystème Suricate

Makina Corpus, missionnée par le département du Gard, et en collaboration avec le Ministère chargé des Sports ainsi que la société Arut@m, développe une intégration du dispositif Suricate aux applications Geotrek-Rando et Geotrek-Admin.

Voir l'article
15/04/2021

Comment migrer vers une version récente de Django ?

Que ce soit pour avoir les dernières fonctionnalités ou les correctifs de sécurité, rester sur une version récente de Django est important pour la pérennité de son projet.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus