{"title":"Production de PDF avec Django","version":"1.9","locale":"fr","docname":"howto/outputting-pdf","url":"/fr/1.9/howto/outputting-pdf/","canonical":"https://djangodocs.dev/fr/1.9/howto/outputting-pdf/","summary":"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…","html":"<h1>Production de PDF avec Django<a class=\"heading-anchor\" href=\"#outputting-pdfs-with-django\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>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 <a class=\"reference external\" href=\"http://www.reportlab.com/opensource/\">ReportLab</a>.</p>\n<p>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.</p>\n<p>Par exemple, Django était utilisé chez <a class=\"reference external\" href=\"http://www.kusports.com/\">kusports.com</a> 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 ».</p>\n<section id=\"install-reportlab\">\n<h2>Installation de ReportLab<a class=\"heading-anchor\" href=\"#install-reportlab\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>La bibliothèque ReportLab est <a class=\"reference external\" href=\"https://pypi.python.org/pypi/reportlab\">disponible sur PyPI</a>. Un <a class=\"reference external\" href=\"http://www.reportlab.com/docs/reportlab-userguide.pdf\">manuel d’utilisation</a> (un fichier PDF, bien évidemment) est aussi disponible en téléchargement. Vous pouvez installer ReportLab avec <code class=\"docutils literal notranslate\">pip</code>:</p>\n<div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>pip install reportlab\n</code></pre></div>\n<p>Testez votre installation en l’important dans l’interpréteur interactif de Python :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">import</span> <span class=\"nn\">reportlab</span>\n</code></pre></div>\n<p>Si cette commande ne produit aucune erreur, l’installation a réussi.</p>\n</section>\n<section id=\"write-your-view\">\n<h2>Écriture de la vue<a class=\"heading-anchor\" href=\"#write-your-view\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>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 <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponse</code></a> de Django sont justement des objets de type fichier.</p>\n<p>Voici un exemple « Hello World » :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">reportlab.pdfgen</span> <span class=\"kn\">import</span> canvas\n<span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n\n<span class=\"k\">def</span> <span class=\"nf\">some_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"c1\"># Create the HttpResponse object with the appropriate PDF headers.</span>\n    response <span class=\"o\">=</span> HttpResponse<span class=\"p\">(</span>content_type<span class=\"o\">=</span><span class=\"s1\">&#39;application/pdf&#39;</span><span class=\"p\">)</span>\n    response<span class=\"p\">[</span><span class=\"s1\">&#39;Content-Disposition&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;attachment; filename=&quot;somefilename.pdf&quot;&#39;</span>\n\n    <span class=\"c1\"># Create the PDF object, using the response object as its &quot;file.&quot;</span>\n    p <span class=\"o\">=</span> canvas<span class=\"o\">.</span>Canvas<span class=\"p\">(</span>response<span class=\"p\">)</span>\n\n    <span class=\"c1\"># Draw things on the PDF. Here&#39;s where the PDF generation happens.</span>\n    <span class=\"c1\"># See the ReportLab documentation for the full list of functionality.</span>\n    p<span class=\"o\">.</span>drawString<span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">,</span> <span class=\"mi\">100</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Hello world.&quot;</span><span class=\"p\">)</span>\n\n    <span class=\"c1\"># Close the PDF object cleanly, and we&#39;re done.</span>\n    p<span class=\"o\">.</span>showPage<span class=\"p\">()</span>\n    p<span class=\"o\">.</span>save<span class=\"p\">()</span>\n    <span class=\"k\">return</span> response\n</code></pre></div>\n<p>Le code et les commentaires sont assez explicites, mais certains points méritent un éclaircissement :</p>\n<ul>\n<li><p>La réponse est initialisée avec un type MIME spécial, <em class=\"mimetype\">application/pdf</em>. Ceci indique aux navigateurs que le document est un fichier PDF, et non pas un fichier HTML. Si vous omettiez ce paramètre, les navigateurs interpréteraient probablement le contenu comme du HTML, ce qui résulterait en un affichage cryptique aux allures de code secret.</p></li>\n<li><p>L’en-tête <code class=\"docutils literal notranslate\">Content-Disposition</code> de la réponse est aussi défini avec le nom du fichier PDF. Ce nom est totalement arbitraire, donnez-lui le nom que vous voulez. Il sera notamment utilisé par les navigateurs dans la boîte de dialogue « Enregistrer sous ».</p></li>\n<li><p>Dans cet exemple, l’en-tête <code class=\"docutils literal notranslate\">Content-Disposition</code> commence par <code class=\"docutils literal notranslate\">'attachment; '</code>. Cela force 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 vous omettez <code class=\"docutils literal notranslate\">'attachment;'</code>, les navigateurs gèrent directement le fichier PDF en utilisant le programme ou greffon qui aura été configuré pour les liens PDF. Voici à quoi un tel code ressemblerait :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>response<span class=\"p\">[</span><span class=\"s1\">&#39;Content-Disposition&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;filename=&quot;somefilename.pdf&quot;&#39;</span>\n</code></pre></div>\n</li>\n<li><p>Le branchement à l’API ReportLab est facile : il suffit de passer <code class=\"docutils literal notranslate\">response</code> comme premier paramètre à <code class=\"docutils literal notranslate\">canvas.Canvas</code>. La classe <code class=\"docutils literal notranslate\">Canvas</code> s’attend à un objet de type fichier et <a class=\"reference internal\" href=\"/fr/1.9/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\">HttpResponse</code></a> joue très bien ce rôle.</p></li>\n<li><p>Notez que toute méthode de génération PDF subséquente est appelée sur l’objet PDF (<code class=\"docutils literal notranslate\">p</code> dans ce cas), et non pas sur <code class=\"docutils literal notranslate\">response</code>.</p></li>\n<li><p>Finalement, il est important d’appeler <code class=\"docutils literal notranslate\">showPage()</code> et <code class=\"docutils literal notranslate\">save()</code> sur le fichier PDF.</p></li>\n</ul>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>ReportLab n’est pas « thread-safe ». Certains utilisateurs ont signalé des problèmes bizarres lorsque des vues Django de production de PDF sont simultanément appelées par beaucoup de monde.</p>\n</aside>\n</section>\n<section id=\"complex-pdfs\">\n<h2>PDF complexes<a class=\"heading-anchor\" href=\"#complex-pdfs\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Si vous créez un document PDF complexe avec ReportLab, envisagez l’utilisation de la bibliothèque <a class=\"reference external\" href=\"https://docs.python.org/3/library/io.html#module-io\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\">io</code></a> comme espace de stockage temporaire du fichier PDF. Cette bibliothèque fournit une interface d’objet de type fichier particulièrement efficace. Voici l’exemple « Hello World » ci-dessus réécrit en utilisant <a class=\"reference external\" href=\"https://docs.python.org/3/library/io.html#module-io\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\">io</code></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span> <span class=\"nn\">io</span> <span class=\"kn\">import</span> BytesIO\n<span class=\"kn\">from</span> <span class=\"nn\">reportlab.pdfgen</span> <span class=\"kn\">import</span> canvas\n<span class=\"kn\">from</span> <span class=\"nn\">django.http</span> <span class=\"kn\">import</span> HttpResponse\n\n<span class=\"k\">def</span> <span class=\"nf\">some_view</span><span class=\"p\">(</span>request<span class=\"p\">):</span>\n    <span class=\"c1\"># Create the HttpResponse object with the appropriate PDF headers.</span>\n    response <span class=\"o\">=</span> HttpResponse<span class=\"p\">(</span>content_type<span class=\"o\">=</span><span class=\"s1\">&#39;application/pdf&#39;</span><span class=\"p\">)</span>\n    response<span class=\"p\">[</span><span class=\"s1\">&#39;Content-Disposition&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;attachment; filename=&quot;somefilename.pdf&quot;&#39;</span>\n\n    buffer <span class=\"o\">=</span> BytesIO<span class=\"p\">()</span>\n\n    <span class=\"c1\"># Create the PDF object, using the BytesIO object as its &quot;file.&quot;</span>\n    p <span class=\"o\">=</span> canvas<span class=\"o\">.</span>Canvas<span class=\"p\">(</span>buffer<span class=\"p\">)</span>\n\n    <span class=\"c1\"># Draw things on the PDF. Here&#39;s where the PDF generation happens.</span>\n    <span class=\"c1\"># See the ReportLab documentation for the full list of functionality.</span>\n    p<span class=\"o\">.</span>drawString<span class=\"p\">(</span><span class=\"mi\">100</span><span class=\"p\">,</span> <span class=\"mi\">100</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Hello world.&quot;</span><span class=\"p\">)</span>\n\n    <span class=\"c1\"># Close the PDF object cleanly.</span>\n    p<span class=\"o\">.</span>showPage<span class=\"p\">()</span>\n    p<span class=\"o\">.</span>save<span class=\"p\">()</span>\n\n    <span class=\"c1\"># Get the value of the BytesIO buffer and write it to the response.</span>\n    pdf <span class=\"o\">=</span> buffer<span class=\"o\">.</span>getvalue<span class=\"p\">()</span>\n    buffer<span class=\"o\">.</span>close<span class=\"p\">()</span>\n    response<span class=\"o\">.</span>write<span class=\"p\">(</span>pdf<span class=\"p\">)</span>\n    <span class=\"k\">return</span> response\n</code></pre></div>\n</section>\n<section id=\"further-resources\">\n<h2>Ressources complémentaires<a class=\"heading-anchor\" href=\"#further-resources\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<ul class=\"simple\">\n<li><p><a class=\"reference external\" href=\"http://www.pdflib.org/\">PDFlib</a> est une autre bibliothèque de génération de PDF offrant une interface Python. Pour l’utiliser avec Django, vous pouvez exploiter les mêmes concepts que ceux présentés dans cet article.</p></li>\n<li><p><a class=\"reference external\" href=\"https://github.com/xhtml2pdf/xhtml2pdf\">XHTML2PDF</a> est encore une autre bibliothèque de génération de PDF. Elle est livrée avec un exemple de la façon de l’intégrer à Django.</p></li>\n<li><p><a class=\"reference external\" href=\"https://www.msweet.org/projects.php?Z1\">HTMLdoc</a> est un script en ligne de commande qui sait convertir du HTML en PDF. Il ne présente pas d’interface Python, mais il est possible d’appeler des commandes de shell avec <code class=\"docutils literal notranslate\">system</code> ou <code class=\"docutils literal notranslate\">popen</code> et de récupérer le résultat depuis Python.</p></li>\n</ul>\n</section>\n<section id=\"other-formats\">\n<h2>Autres formats<a class=\"heading-anchor\" href=\"#other-formats\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Vous constaterez que ces exemples ne contiennent pas beaucoup de code spécifique au format PDF, uniquement les parties utilisant <code class=\"docutils literal notranslate\">reportlab</code>. Vous pouvez donc employer des techniques semblables pour générer tout autre format pour lequel vous trouvez une bibliothèque Python. Consultez également <a class=\"reference internal\" href=\"/fr/1.9/howto/outputting-csv/\"><span class=\"doc\">Production de CSV avec Django</span></a>, un autre exemple qui contient certaines techniques utilisables lors de la génération de formats basés sur du texte.</p>\n</section>","rootId":"outputting-pdfs-with-django","toc":[{"title":"Installation de ReportLab","anchor":"install-reportlab","children":[]},{"title":"Écriture de la vue","anchor":"write-your-view","children":[]},{"title":"PDF complexes","anchor":"complex-pdfs","children":[]},{"title":"Ressources complémentaires","anchor":"further-resources","children":[]},{"title":"Autres formats","anchor":"other-formats","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"Guides pratiques","url":"/fr/1.9/howto/"}],"prev":{"docname":"howto/outputting-csv","title":"Production de CSV avec Django","url":"/fr/1.9/howto/outputting-csv/"},"next":{"docname":"howto/static-files/index","title":"Gestion des fichiers statiques (par ex. images, JavaScript, CSS)","url":"/fr/1.9/howto/static-files/"},"formats":{"html":"/fr/1.9/howto/outputting-pdf/","markdown":"/fr/1.9/howto/outputting-pdf.md","json":"/fr/1.9/howto/outputting-pdf.json"},"source":"https://github.com/django/django/blob/stable/1.9.x/docs/howto/outputting-pdf.txt","official":"https://docs.djangoproject.com/fr/1.9/howto/outputting-pdf/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","fr","ja","id","pt-br","es"]}