Accueil / Blog / Métier / 2013 / Générer des documents bureautiques avec Django

Générer des documents bureautiques avec Django

Par Mathieu Leplatre publié 17/09/2013
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.
Générer des documents bureautiques avec 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 !

/blog/metier/appy-pod-template/image

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
/blog/metier/appy-pod-rendered/image

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 :

ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
Python : Bien configurer son environnement de développement Python : Bien configurer son environnement de développement 07/12/2015

Comment utiliser les bonnes pratiques de développement Python.

Formation Django initiation à Toulouse du 13 au 15 mars Formation Django initiation à Toulouse du 13 au 15 mars 26/01/2017

Entrez de plain-pied dans l'univers de Django aux côtés de développeurs ayant une expérience de ...

Retour sur la PyConFr 2016 Retour sur la PyConFr 2016 18/10/2016

Nous étions présents à Rennes pour PyConFr 2016. Voici notre compte-rendu à chaud.

Wagtail: How to use the Page model and its manager (part 2) Wagtail: How to use the Page model and its manager (part 2) 08/08/2016

The Page model has several methods specific to Wagtail. This is also the case of its manager. We ...

Wagtail : How to make your own content type models (part 1) Wagtail : How to make your own content type models (part 1) 29/07/2016

We are used to initialize our CMS directly from a web interface, often including lots of complex ...