# documentação Django 2.0.8

# Emitindo CSV com Django

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')
        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

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.
- Utilizar a API do CSV-generation é fácil: Apenas passe `response``como o primeiro argumento para ``csv.writer`. A função `csv.writer` espera um objeto “file-like”, e o objetos `HttpResponse` é um “file-loke”.
- Para cada linha no seu arquivo CSV, chame `writer.writerow`, passando-o para um objeto interável tal como uma lista ou tupla.
- O módulo CSV cuida das aspas pra você, então não tem que se preocupar em substituir strings com aspas ou vírgulas. Apenas passe as string para `writerow()`, e ele fará a coisa certa.

### 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.

Neste exemplo, fazemos uso total de geradores Python para manipular eficientemente a montagem e transmissão de um grande arquivo CSV:

    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

## 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 Context, 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 = Context({
            '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 %}

Este template é bem básico. Ele somente itera sobre o dado enviado e mostra uma linha de CSV para cada linha. Isso usa o filtro de template `addslashes` para se assegurar que não haverá nenhum problema com aspas.

## 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 Gerando PDFs com o Django por exemplo.