# Documentation Django 3.1.9.dev

# Production de CSV avec Django

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.

## La bibliothèque CSV de Python

Python contient une bibliothèque CSV, `csv`. L’élément clé dans son utilisation avec Django est que les fonctionnalités de création de CSV du module `csv` agissent sur des objets de type fichier, et les objets `HttpResponse` de Django sont justement des objets de type fichier.

Voici un exemple :

    import csv
    from django.http import HttpResponse

    def some_view(request):
        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'

        writer = csv.writer(response)
        writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
        writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])

        return response

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

- La réponse est initialisée avec un type MIME spécial, text/csv. 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.
- L’en-tête `Content-Disposition` 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 ».
- Il est possible de se brancher à l’API de génération de CSV en passant `response` comme premier paramètre à `csv.writer`. La fonction `csv.writer` s’attend à un objet de type fichier et `HttpResponse` joue très bien ce rôle.
- Pour chaque ligne de votre fichier CSV, appelez `writer.writerow` en lui passant un objet itérable.
- 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 à `writerow()` et il s’occupera de faire ce qu’il faut.

### Diffusion continue de fichiers CSV volumineux

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 `StreamingHttpResponse`. 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.

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 :

    import csv

    from django.http import StreamingHttpResponse

    class Echo:
        """An object that implements just the write method of the file-like
        interface.
        """
        def write(self, value):
            """Write the value by returning it, instead of storing in a buffer."""
            return value

    def some_streaming_csv_view(request):
        """A view that streams a large CSV file."""
        # Generate a sequence of rows. The range is based on the maximum number of
        # rows that can be handled by a single sheet in most spreadsheet
        # applications.
        rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
        pseudo_buffer = Echo()
        writer = csv.writer(pseudo_buffer)
        response = StreamingHttpResponse((writer.writerow(row) for row in rows),
                                         content_type="text/csv")
        response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
        return response

## Utilisation du système de gabarits

Vous avez aussi la possibilité d’utiliser le système de gabarits de Django pour produire le CSV. Cette technique est de plus bas niveau que l’utilisation du module Python `csv`, mais cette alternative est présentée ici par souci d’exhaustivité.

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 `for`.

Voici un exemple qui génère le même fichier CSV que ci-dessus :

    from django.http import HttpResponse
    from django.template import loader

    def some_view(request):
        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'

        # The data is hard-coded here, but you could load it from a database or
        # some other source.
        csv_data = (
            ('First row', 'Foo', 'Bar', 'Baz'),
            ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
        )

        t = loader.get_template('my_template_name.txt')
        c = {'data': csv_data}
        response.write(t.render(c))
        return response

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 `content_type='text/csv'`) est identique.

Puis, créez le gabarit `my_template_name.txt` avec ce contenu :

    {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
    {% endfor %}

Ce court gabarit parcourt les données reçues et affiche une ligne de CSV pour chaque ligne. Il utilise le filtre de gabarit `addslashes` pour s’assurer qu’il n’y aura pas de problèmes avec les guillemets.

## Autres formats textuels

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 Production de PDF avec Django pour voir un exemple.