{"title":"Création de contenu CSV","version":"5.2","locale":"fr","docname":"howto/outputting-csv","url":"/fr/5.2/howto/outputting-csv/","canonical":"https://djangodocs.dev/fr/5.2/howto/outputting-csv/","summary":"Ce document explique comment produire dynamiquement du contenu CSV (Comma Separated Values) en utilisant des vues Django. Pour cela, vous pouvez soit utiliser la…","html":"<h1>Création de contenu CSV<a class=\"heading-anchor\" href=\"#how-to-create-csv-output\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Ce document explique comment produire dynamiquement du contenu CSV (Comma Separated Values) en utilisant des vues Django. Pour cela, vous pouvez soit utiliser la bibliothèque CSV de Django, soit le système de gabarits de Django.</p>\n<section id=\"using-the-python-csv-library\">\n<h2>La bibliothèque CSV de Python<a class=\"heading-anchor\" href=\"#using-the-python-csv-library\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Python contient une bibliothèque CSV, <a class=\"reference external\" href=\"https://docs.python.org/3/library/csv.html#module-csv\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">csv</span></code></a>. L’élément clé dans son utilisation avec Django est que les fonctionnalités de création de CSV du module <a class=\"reference external\" href=\"https://docs.python.org/3/library/csv.html#module-csv\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">csv</span></code></a> agissent sur des objets de type fichier, et les objets <a class=\"reference internal\" href=\"/fr/5.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> de Django sont justement des objets de type fichier.</p>\n<p>Voici un exemple :</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\">import</span><span class=\"w\"> </span><span class=\"nn\">csv</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">some_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"c1\"># Create the HttpResponse object with the appropriate CSV header.</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span>\n        <span class=\"n\">content_type</span><span class=\"o\">=</span><span class=\"s2\">&quot;text/csv&quot;</span><span class=\"p\">,</span>\n        <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;Content-Disposition&quot;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;attachment; filename=&quot;somefilename.csv&quot;&#39;</span><span class=\"p\">},</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"n\">writer</span> <span class=\"o\">=</span> <span class=\"n\">csv</span><span class=\"o\">.</span><span class=\"n\">writer</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">)</span>\n    <span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">writerow</span><span class=\"p\">([</span><span class=\"s2\">&quot;First row&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Foo&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Bar&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Baz&quot;</span><span class=\"p\">])</span>\n    <span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">writerow</span><span class=\"p\">([</span><span class=\"s2\">&quot;Second row&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;A&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;B&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;C&quot;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&quot;Testing&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Here&#39;s a quote&quot;</span><span class=\"p\">])</span>\n\n    <span class=\"k\">return</span> <span class=\"n\">response</span>\n</code></pre></div>\n<p>Le code et les commentaires sont assez explicites, mais certains points méritent un éclaircissement :</p>\n<ul class=\"simple\">\n<li><p>La réponse est initialisée avec un type MIME spécial, <em class=\"mimetype\">text/csv</em>. Ceci indique aux navigateurs que le document est un fichier CSV, 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\"><span class=\"pre\">Content-Disposition</span></code> de la réponse est aussi défini avec le nom du fichier CSV. 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>Il est possible de se brancher à l’API de génération de CSV en passant <code class=\"docutils literal notranslate\"><span class=\"pre\">response</span></code> comme premier paramètre à <code class=\"docutils literal notranslate\"><span class=\"pre\">csv.writer</span></code>. La fonction <code class=\"docutils literal notranslate\"><span class=\"pre\">csv.writer</span></code> s’attend à un objet de type fichier et <a class=\"reference internal\" href=\"/fr/5.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code></a> joue très bien ce rôle.</p></li>\n<li><p>Pour chaque ligne de votre fichier CSV, appelez <code class=\"docutils literal notranslate\"><span class=\"pre\">writer.writerow</span></code> en lui passant un objet <a class=\"reference external\" href=\"https://docs.python.org/3/glossary.html#term-iterable\" title=\"(disponible dans Python v3.14)\"><span class=\"xref std std-term\">itérable</span></a>.</p></li>\n<li><p>Le module CSV s’occupe des guillemets, vous n’avez donc pas besoin de vous soucier d’échapper les chaînes contenant des guillemets ou des virgules. Passez vos chaînes brutes à <code class=\"docutils literal notranslate\"><span class=\"pre\">writerow()</span></code> et il s’occupera de faire ce qu’il faut.</p></li>\n</ul>\n<section id=\"streaming-large-csv-files\">\n<span id=\"streaming-csv-files\"></span><h3>Diffusion continue de fichiers CSV volumineux<a class=\"heading-anchor\" href=\"#streaming-large-csv-files\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque vous avez affaire à des vues qui génèrent des réponses très grandes, il faut considérer l’utilisation de réponses <a class=\"reference internal\" href=\"/fr/5.2/ref/request-response/#django.http.StreamingHttpResponse\" title=\"django.http.StreamingHttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StreamingHttpResponse</span></code></a>. Par exemple, avec la diffusion continue d’un fichier qui prend beaucoup de temps à générer, vous pouvez éviter la perte de connexion de l’équilibreur de charge qui, autrement, aurait expiré pendant que le serveur générait la réponse.</p>\n<p>Dans cet exemple, nous utilisons pleinement les générateurs Python pour gérer efficacement l’assemblage et la transmission d’un fichier CSV volumineux :</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\">import</span><span class=\"w\"> </span><span class=\"nn\">csv</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">StreamingHttpResponse</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Echo</span><span class=\"p\">:</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;An object that implements just the write method of the file-like</span>\n<span class=\"sd\">    interface.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">write</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">value</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;Write the value by returning it, instead of storing in a buffer.&quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"n\">value</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">some_streaming_csv_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;A view that streams a large CSV file.&quot;&quot;&quot;</span>\n    <span class=\"c1\"># Generate a sequence of rows. The range is based on the maximum number of</span>\n    <span class=\"c1\"># rows that can be handled by a single sheet in most spreadsheet</span>\n    <span class=\"c1\"># applications.</span>\n    <span class=\"n\">rows</span> <span class=\"o\">=</span> <span class=\"p\">([</span><span class=\"s2\">&quot;Row </span><span class=\"si\">{}</span><span class=\"s2\">&quot;</span><span class=\"o\">.</span><span class=\"n\">format</span><span class=\"p\">(</span><span class=\"n\">idx</span><span class=\"p\">),</span> <span class=\"nb\">str</span><span class=\"p\">(</span><span class=\"n\">idx</span><span class=\"p\">)]</span> <span class=\"k\">for</span> <span class=\"n\">idx</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"mi\">65536</span><span class=\"p\">))</span>\n    <span class=\"n\">pseudo_buffer</span> <span class=\"o\">=</span> <span class=\"n\">Echo</span><span class=\"p\">()</span>\n    <span class=\"n\">writer</span> <span class=\"o\">=</span> <span class=\"n\">csv</span><span class=\"o\">.</span><span class=\"n\">writer</span><span class=\"p\">(</span><span class=\"n\">pseudo_buffer</span><span class=\"p\">)</span>\n    <span class=\"k\">return</span> <span class=\"n\">StreamingHttpResponse</span><span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"n\">writer</span><span class=\"o\">.</span><span class=\"n\">writerow</span><span class=\"p\">(</span><span class=\"n\">row</span><span class=\"p\">)</span> <span class=\"k\">for</span> <span class=\"n\">row</span> <span class=\"ow\">in</span> <span class=\"n\">rows</span><span class=\"p\">),</span>\n        <span class=\"n\">content_type</span><span class=\"o\">=</span><span class=\"s2\">&quot;text/csv&quot;</span><span class=\"p\">,</span>\n        <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;Content-Disposition&quot;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;attachment; filename=&quot;somefilename.csv&quot;&#39;</span><span class=\"p\">},</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"using-the-template-system\">\n<h2>Utilisation du système de gabarits<a class=\"heading-anchor\" href=\"#using-the-template-system\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Vous avez aussi la possibilité d’utiliser le <a class=\"reference internal\" href=\"/fr/5.2/topics/templates/\"><span class=\"doc\">système de gabarits de Django</span></a> pour produire le CSV. Cette technique est de plus bas niveau que l’utilisation du module Python <a class=\"reference external\" href=\"https://docs.python.org/3/library/csv.html#module-csv\" title=\"(disponible dans Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">csv</span></code></a>, mais cette alternative est présentée ici par souci d’exhaustivité.</p>\n<p>L’idée ici est de passer une liste d’éléments à un gabarit qui se chargera de générer les virgules dans une boucle <a class=\"reference internal\" href=\"/fr/5.2/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">for</span></code></a>.</p>\n<p>Voici un exemple qui génère le même fichier CSV que ci-dessus :</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=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.template</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">loader</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">some_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"c1\"># Create the HttpResponse object with the appropriate CSV header.</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span>\n        <span class=\"n\">content_type</span><span class=\"o\">=</span><span class=\"s2\">&quot;text/csv&quot;</span><span class=\"p\">,</span>\n        <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;Content-Disposition&quot;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;attachment; filename=&quot;somefilename.csv&quot;&#39;</span><span class=\"p\">},</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"c1\"># The data is hard-coded here, but you could load it from a database or</span>\n    <span class=\"c1\"># some other source.</span>\n    <span class=\"n\">csv_data</span> <span class=\"o\">=</span> <span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"s2\">&quot;First row&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Foo&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Bar&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Baz&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">(</span><span class=\"s2\">&quot;Second row&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;A&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;B&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;C&quot;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;&quot;Testing&quot;&#39;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Here&#39;s a quote&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n\n    <span class=\"n\">t</span> <span class=\"o\">=</span> <span class=\"n\">loader</span><span class=\"o\">.</span><span class=\"n\">get_template</span><span class=\"p\">(</span><span class=\"s2\">&quot;my_template_name.txt&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;data&quot;</span><span class=\"p\">:</span> <span class=\"n\">csv_data</span><span class=\"p\">}</span>\n    <span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">write</span><span class=\"p\">(</span><span class=\"n\">t</span><span class=\"o\">.</span><span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">c</span><span class=\"p\">))</span>\n    <span class=\"k\">return</span> <span class=\"n\">response</span>\n</code></pre></div>\n<p>La seule différence entre cet exemple et le précédent est que celui-ci utilise le chargement d’un gabarit à la place du module CSV. Le reste du code (comme <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type='text/csv'</span></code>) est identique.</p>\n<p>Puis, créez le gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">my_template_name.txt</span></code> avec ce contenu :</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">row</span> <span class=\"k\">in</span> <span class=\"nv\">data</span> <span class=\"cp\">%}</span>&quot;<span class=\"cp\">{{</span> <span class=\"nv\">row.0</span><span class=\"o\">|</span><span class=\"nf\">addslashes</span> <span class=\"cp\">}}</span>&quot;, &quot;<span class=\"cp\">{{</span> <span class=\"nv\">row.1</span><span class=\"o\">|</span><span class=\"nf\">addslashes</span> <span class=\"cp\">}}</span>&quot;, &quot;<span class=\"cp\">{{</span> <span class=\"nv\">row.2</span><span class=\"o\">|</span><span class=\"nf\">addslashes</span> <span class=\"cp\">}}</span>&quot;, &quot;<span class=\"cp\">{{</span> <span class=\"nv\">row.3</span><span class=\"o\">|</span><span class=\"nf\">addslashes</span> <span class=\"cp\">}}</span>&quot;, &quot;<span class=\"cp\">{{</span> <span class=\"nv\">row.4</span><span class=\"o\">|</span><span class=\"nf\">addslashes</span> <span class=\"cp\">}}</span>&quot;\n<span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>Ce court gabarit parcourt les données reçues et affiche une ligne de CSV pour chaque ligne. Il utilise le filtre de gabarit <a class=\"reference internal\" href=\"/fr/5.2/ref/templates/builtins/#std-templatefilter-addslashes\"><code class=\"xref std std-tfilter docutils literal notranslate\"><span class=\"pre\">addslashes</span></code></a> pour s’assurer qu’il n’y aura pas de problèmes avec les guillemets.</p>\n</section>\n<section id=\"other-text-based-formats\">\n<h2>Autres formats textuels<a class=\"heading-anchor\" href=\"#other-text-based-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 CSV, uniquement le format de sortie spécifique. Vous pouvez donc employer l’une de ces techniques pour générer tout autre format basé sur du texte. Vous pouvez aussi utiliser des techniques semblables pour produire n’importe quel contenu binaire ; consultez <a class=\"reference internal\" href=\"/fr/5.2/howto/outputting-pdf/\"><span class=\"doc\">Création de fichiers PDF</span></a> pour voir un exemple.</p>\n</section>","rootId":"how-to-create-csv-output","toc":[{"title":"La bibliothèque CSV de Python","anchor":"using-the-python-csv-library","children":[{"title":"Diffusion continue de fichiers CSV volumineux","anchor":"streaming-large-csv-files","children":[]}]},{"title":"Utilisation du système de gabarits","anchor":"using-the-template-system","children":[]},{"title":"Autres formats textuels","anchor":"other-text-based-formats","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"Guides pratiques","url":"/fr/5.2/howto/"}],"prev":{"docname":"howto/custom-lookups","title":"Écriture d’expressions de requêtes personnalisées","url":"/fr/5.2/howto/custom-lookups/"},"next":{"docname":"howto/outputting-pdf","title":"Création de fichiers PDF","url":"/fr/5.2/howto/outputting-pdf/"},"formats":{"html":"/fr/5.2/howto/outputting-csv/","markdown":"/fr/5.2/howto/outputting-csv.md","json":"/fr/5.2/howto/outputting-csv.json"},"source":"https://github.com/django/django/blob/stable/5.2.x/docs/howto/outputting-csv.txt","official":"https://docs.djangoproject.com/fr/5.2/howto/outputting-csv/","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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}