Exportando CSV com o Django¶
Este documento explica como gerar CSV (Valores Separados por Vírgulas) dinamicamente usando views do Django.Para fazer isso, você pode utilizar a biblioteca Python CSV ou o sistema de templates do Django.
Python comes with a CSV library, csv
. The key to using it with Django is
that the csv
module’s CSV-creation capability acts on file-like objects, and
Django’s HttpResponse
objects are file-like objects.
Usando a biblioteca Python CSV¶
O Python vem com uma biblioteca CSV, csv
. A chave para usá-la com o Django
é que a capacidade de criação de CSV do módulo csv
recai em objetos que
equivalem a arquivos, e objetos HttpResponse
do Django são
deste tipo.
Aqui tem um exemplo:
import csv
from django.http import HttpResponse
def some_view(request):
# Cria o objeto HttpResponse com o cabeçalho CSV apropriado.
response = HttpResponse(mimetype='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ários devem ser auto-explicativos, mas algumas coisas merecem ser mencionadas:
- O response pega um mimetype especial,
text/csv
. Isso avisa aos navegadores que o documento é um arquivo CSV, em vez de um arquivo HTML. Se você deixar isso desligado, os navegadores provavelmente irão interpretar a saída com um HTML, o que resultará em feiúra, um assustador gobbledygook (deve ser um ser epacial) na sua janela do navegador. - O response pega um cabeçalho adicional
Content-Disposition
, que contém o nome do arquivo CSV. Esse nome de arquivo é arbritário; chame-o como quiser. Ele será usado pelos navegadores em caixas de diálogo “Salvar como...”, etc. - Usar hooks na API de geração do CSV é fácil: Simplesmente passe
response
como o primeiro argumento paracsv.writer
. A funçãocsv.writer
espera um objeto semelhante a um arquivo e objetosHttpResponse
são justamente isso. - Para cada linha em seu arquivo CSV, chame
writer.writerow
, passando-o um objeto iterável como uma lista ou tupla. - O módulo CSV se preocupa em escapar por você, então você não tem de se
preocupar em escapar strings com aspas ou vírgulas. Somente passe para o
writerow()
suas strings normalmente, e ele irá fazer a coisa certa.
Usando o sistema de template¶
Alternativamente, você pode usar o sistema de template do Django para gerar CSV. Isso é mais baixo nível do que usar a biblioteca CSV, mas a solução é apresentada para fins de complementação.
A idéia aqui é passar uma lista de itens para o seu template e ter a saída
separada por vírgulas através de uma tag de loop for
.
Aqui vai um exemplo, que gera o mesmo arquivo CSV do outro exemplo:
from django.http import HttpResponse
from django.template import loader, Context
def some_view(request):
# Cria o objeto HttpResponse com o cabeçalho CSV apropriado.
response = HttpResponse(mimetype='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.
# Aqui os dados estão embutidos no código, mas você poderia carregá-lo
# de um banco de dados ou de alguma outra fonte.
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
This template is quite basic. It just 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.
A única diferença entre esse exemplo e o anterior, é que esse usa o carregador
de templates em vez do módulo CSV. O resto do código – tais como o
mimetype='text/csv'
– é o mesmo.
Então crie um template my_template_name.txt
com este código:
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}
Este template é muito básico. Ele somente itera sobre o dado passado e mostra
uma linha de CSV para cada linha. Ele usa o filtro de template
addslashes
para assegurar que não haja quaisquer problemas com aspas.
Outro formato baseado em texto¶
Repare que não existe muita especificidade para CSV aqui – somente o formato de saída. Você pode usar qualquer destas técnicas para gerar saída de qualquer formato baseado em texto que você sonhar. Você pode também usar uma técnica similar para gerar dados binários; veja Exportando PDFs com o Django por exemplo.