Exportando PDFs com o Django¶
Este documento explora como exportar arquivos PDF dinamicamente usando views do Django. Isso é possível graças a uma excelente, biblioteca PDF de código-aberto para Python, chamada ReportLab.
A vantagem de gerar dinamicamente arquivos PDF é que você pode criar PDFs customizados para diferentes propósitos – como para diferentes usuários ou diferentes partes de conteúdos.
Por exemplo, o Django foi usado no kusports.com para gerar versões de impressão curtomizadas dos torneios do NCAA, como arquivos PDF, para pessoas participantes no concurso March Madness.
Instalando o ReportLab¶
Baixe e instale a biblioteca ReportLab do site http://www.reportlab.org/downloads.html. O guia de usuário (não coincidentemente, um arquivo PDF) explica como instalá-lo.
Teste sua instalação importando-o no interpretador interativo do Python:
>>> import reportlab
Se o comando não mostrar nenhum erro, a instalação está funcionando.
Escreva o seu view¶
A chave para gerar PDFs dinamicamente com o Django é que a API do ReportLab
trabalha sobre objetos que se comportam como arquivos, e objetos
HttpResponse
do Django são objetos assim.
Aqui vai um exemplo “Hello World”:
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Crie o objeto HttpResponse com o cabeçalho de PDF apropriado.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
# Crie o objeto PDF, usando o objeto response como seu "arquivo".
p = canvas.Canvas(response)
# Desenhe coisas no PDF. Aqui é onde a geração do PDF acontece.
# Veja a documentação do ReportLab para a lista completa de
# funcionalidades.
p.drawString(100, 100, "Hello world.")
# Feche o objeto PDF, e está feito.
p.showPage()
p.save()
return response
O código e comentários devem ser auto-explicativos, mas umas poucas coisas merecem ser mencionadas:
O response recebe um mimetype especial,
application/pdf
. Isso informa ao navegador que o documento é um arquivo PDF, em vez de um arquivo HTML. Se você não informar isto, o navegador irá provavelmente interpretar a saída como um HTML, o que poderia resultar em um resultado feio e assustador na janela do navegador.O response recebe um cabeçalho adicional
Content-Disposition
, que contém o nome do arquivo PDF. Esse nome de arquivo é arbitrário: chame-o como quiser. Ele será usado pelo navegador na caixa de diálogo “Salvar como...”, etc.O cabeçalho
Content-Disposition
começa com'attachment; '
neste exemplo. Isso força o navegador a mostrar uma caixa de diálogo avisando/confirmando como manipular o documento, mesmo se um padrão está definido na máquina. Se você não informar o'attachment'
, o navegador manipulará o PDF usando qualquer programa/plugin que ele tiver configurado para usar com PDFs. Veja como esse código se pareceria:response['Content-Disposition'] = 'filename=algum_nomedearquivo.pdf'
Usar hooks da API do ReportLab é fácil: somente passe
response
como o primeiro argumento para ocanvas.Canvas
. A classeCanvas
recebe um objeto como arquivo, e objetosHttpResponse
atendem a esse requisito.Note que todo método subseqüente de geração de PDF é chamado no objeto PDF (neste caso,
p
) – não noresponse
.Finalmente, é importante chamar
showPage()
esave()
sobre o arquivo PDF.
PDFs complexos¶
Se você está criando um documento PDF complexo com o ReportLab, considere a
utilização da biblioteca cStringIO como um manipulador temporário para o seu
arquivo PDF. A biblioteca cStringIO fornece uma interface para objeto como
arquivo que é particularmente eficiente. Aqui o exemplo acima “Hello World” é
re-escrito para usar o cStringIO
:
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Crie o objeto HttpResponse com o cabeçalho PDF apropriado.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
buffer = StringIO()
# Crie um objeto PDF, usando o objeto StringIO como seu "arquivo."
p = canvas.Canvas(buffer)
# Desenhe coisas no PDF. Aqui é onde a geração do PDF acontece.
# Veja a documentação do ReportLab para a lista completa de
# funcionalidades.
p.drawString(100, 100, "Hello world.")
# Feche o objeto PDF.
p.showPage()
p.save()
# Pegue o valor do buffer StringIO e escreva-o para o response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
Mais recursos¶
- PDFlib é outra biblioteca de geração de PDF que tem binding para o Python. Para usá-lo com o Django, somente use o mesmo conceito explicado neste artigo.
- Pisa HTML2PDF é mais uma biblioteca de geração de PDF. Pisa é entregue com um exemplo de como integrá-la com o Django.
- HTMLdoc é um script de linha de comando que consegue converter HTML para
PDF. Ele não possui uma interface Python, mas você consegue escapar do
terminal usando
system
oupopen
e recebendo a saída no Python. - forge_fdf no Python é uma biblioteca que preenche formulários em PDF.
Outros formatos¶
Repare que não há muitos destes exemplos específicos de PDF – somente o que é
usado o reportlab
. Você pode usar uma técnica similar para gerar qualquer
formato que possa ser gerado por uma biblioteca Python. Também veja
Exportando CSV com o Django para outro exemplo e algumas técnicas que você pode
usar quando gera formatos baseados em texto.