Création de fichiers PDFLien vers cette rubrique

Ce document explique comment produire des fichiers PDF dynamiquement en utilisant des vues Django. C’est possible grâce à l’excellente bibliothèque Python libre ReportLab.

L’avantage de générer des fichiers PDF dynamiquement est que vous pouvez créer des PDF personnalisés pour différents besoins, par exemple en fonction des utilisateurs ou de certaines parties de contenu.

Par exemple, Django était utilisé chez kusports.com pour générer des tableaux de tournois NCAA personnalisés et prêts pour l’impression, sous forme de fichiers PDF, pour les personnes participant au concours « March Madness ».

Installation de ReportLabLien vers cette rubrique

La bibliothèque ReportLab est disponible sur PyPI. Un manuel d’utilisation (un fichier PDF, bien évidemment) est aussi disponible en téléchargement. Vous pouvez installer ReportLab avec pip:

Linux / macOS

Shell
$ python -m pip install reportlab

Windows

Windows
...\> py -m pip install reportlab

Testez votre installation en l’important dans l’interpréteur interactif de Python :

Python console
>>> import reportlab

Si cette commande ne produit aucune erreur, l’installation a réussi.

Écriture de la vueLien vers cette rubrique

L’élément clé dans la génération dynamique de PDF avec Django est que l’API de ReportLab agit sur des objets de type fichier, et les objets FileResponse de Django acceptent des objets de type fichier.

Voici un exemple « Hello World » :

Code
import io
from django.http import FileResponse
from reportlab.pdfgen import canvas


def some_view(request):
    # Create a file-like buffer to receive PDF data.
    buffer = io.BytesIO()

    # Create the PDF object, using the buffer as its "file."
    p = canvas.Canvas(buffer)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()

    # FileResponse sets the Content-Disposition header so that browsers
    # present the option to save the file.
    buffer.seek(0)
    return FileResponse(buffer, as_attachment=True, filename="hello.pdf")

Le code et les commentaires sont assez explicites, mais certains points méritent un éclaircissement :

  • La réponse définit automatiquement le type MIME application/pdf en se basant sur l’extension du nom de fichier. Ceci indique aux navigateurs que le document est un fichier PDF, et non pas un fichier HTML ou autre contenu binaire générique de type application/octet-stream.

  • Lorsque as_attachment=True est transmis à FileResponse, l’en-tête Content-Disposition est défini en conséquence et pousse les navigateurs Web à ouvrir une boîte de dialogue demandant comment gérer le document, même si un comportement par défaut est défini sur la machine. Si le paramètre as_attachment est omis, les navigateurs gèrent directement le fichier PDF en utilisant le programme ou greffon qui aura été configuré pour les fichiers PDF.

  • Vous pouvez indiquer le paramètre filename de votre choix. Ce contenu sera utilisé dans les boîtes de dialoque Enregistrer sous….

  • Il est possible de se brancher à l’API ReportLab : le même tampon transmis comme premier paramètre à canvas.Canvas peut être passé à la classe FileResponse.

  • Notez que toute méthode de génération PDF subséquente est appelée sur l’objet PDF (p dans ce cas), et non pas sur buffer.

  • Finalement, il est important d’appeler showPage() et save() sur le fichier PDF.

Autres formatsLien vers cette rubrique

Vous constaterez que ces exemples ne contiennent pas beaucoup de code spécifique au format PDF, uniquement les parties utilisant reportlab. Vous pouvez donc employer des techniques semblables pour générer tout autre format pour lequel vous trouvez une bibliothèque Python. Consultez également Création de contenu CSV, un autre exemple qui contient certaines techniques utilisables lors de la génération de formats basés sur du texte.