# Documentação Django 6.0.7

# How to create CSV output

Este documento explica como emitir CSV (valores separados por vírgulas) dinamicamente usando “views” do Django. Para fazer isso, você pode usar a biblioteca CSV do Python ou o sistema de templates do Django.

## Usando a biblioteca CSV do Python.

Python vem com uma biblioteca CSV, `csv`. A chave para usá-lo com Django é que a capacidade CSV-creation do módulo `csv` age como um objeto “file-like”, e aos objetos da class:~django.http.HttpResponse do Django são objetos “file-like”.

Aqui está um exemplo

    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",
            headers={"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

O código e comentário devem ser auto-explanaveis, mas algumas coisas merecem uma menção.

- A resposta recebe um tipo MIME especial text/csv. Isso diz ao browser que o documento é um arquivo CSV, ao invés de um arquivo HTML. Se deixar isso desligado, os browsers vão provavelmente interpretar a resposta como HTML, o qual irá resultar em uma feia e assustadora gobbledygook na janela do seu browser.

- A resposta recebe um cabeçalho adicional `Content-Dispoition`, o qual contém o nome do arquivo CSV. Este nome de arquivo e arbitrário; chame isso do que você quiser. Ele será usado pelo browser no diálogo “Salvar como…”, etc.

- You can hook into the CSV-generation API by passing `response` as the first argument to `csv.writer`. The `csv.writer` function expects a file-like object, and `HttpResponse` objects fit the bill.

- Para cada linha no seu arquivo CSV, chamar o método `writer.writerow`, passando um iterable.

- The CSV module takes care of quoting for you, so you don’t have to worry about escaping strings with quotes or commas in them. Pass `writerow()` your raw strings, and it’ll do the right thing.

### Transmitindo grandes arquivos CSV

Quando lida com “views” que geram respostas muito grandes, talvez queira considerar usar o `StreamingHttpResponse` do Django no lugar. Por exemplo, por trasmitir em fluxo contínuo ou “streaming” um arquivo que leva muito tempo para ser gerado você pode evitar que a conexão seja perdida tentando balancear a carga que talvez expire enquanto o servidor estava gerando a resposta.

In this example, we make full use of Python generators to efficiently handle the assembly and transmission of a large CSV file. Rows are batched together to reduce HTTP overhead and improve compression efficiency when used with `GZipMiddleware`:

    import csv
    from itertools import batched

    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)

        def stream_batched_rows():
            for batch in batched(rows, 100):
                yield "".join(writer.writerow(row) for row in batch)

        return StreamingHttpResponse(
            stream_batched_rows(),
            content_type="text/csv",
            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
        )

## Usando o sistema de template.

Uma alternatica, você pode usar o sistema de tempaltes do Django para gerar CSV. Isso é mais baixo nível que usar o conveniente módulo Python `csv`, mas a solução é apresentada aqui para para abrangência.

A idéia aqui é passar uma lista de itens para seu template, e ter a saida do template as vírgulas em um loop `for`.

Aqui um exemplo, o qual gera o mesmo arquivo CSV que acima:

    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",
            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
        )

        # The data is hardcoded 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

A única diferença entre este exemplo e o exemplo anterior é que este usa carga de template ao invés do módulo CSV. O resto do código – tal como `content_type='text/csv'` – é o mesmo.

Então, crie o template `my_template_name.txt`, com este código no template:

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

This short template iterates over the given data and displays a line of CSV for each row. It uses the `addslashes` template filter to ensure there aren’t any problems with quotes.

## Outros formatos baseados em texto.

Note que não tem muita coisa específica sobre CSV aqui – apenas o formato de saída. Você pode usar qualquer uma destas técnicas para qualquer formato texto que você imagine. Você também pode usar essa técnica para gerar dados binários arbitrários; veja How to create PDF files por exemplo.