Gerando PDFs com o DjangoLink para este cabeçalho

Este documnto explica como gerar arquivos PDF dinamicamente usando “views” Django. Isso é possível através da excelente, biblioteca Python de código-aberto RepostLab .

A vantagem de gerar arquivos PDF dinamicamente é que você pode criar PDFs personalizados para diferentes propósitos – vamos dizer, para diferentes usuários ou diferentes partes de conteúdo.

Por exemplo, o DJango foi usado no kusports.com para gerar relatórios personalizados, prontos para impressão, de pontuação de torneio da NCAA, como arquivos PDF, para pessoas que participam do concurso March Madness.

Instalar o ReportLabLink para este cabeçalho

A biblioteca RepostLab está disponível available on PyPI. Um guia de usuário em user guide (não coincidentemente um arquivo PDF) está disponível para download. Você pode instalar o ReportLab com pip:

Shell
$ pip install reportlab

Teste sua instalação importando no interpretador interativo Python:

Code
>>> import reportlab

Se o comando não emitir nenhum erro, a instalação funciona.

Escreva sua “view”Link para este cabeçalho

A chave para gerar PDF dinamicamente com Django é que a API do ReportLab atua como um objeto “file-like”, e os HttpResponse do Django são objetos “file-like”.

Aqui um exemplo “Hello World”:

Code
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

    # Create the PDF object, using the response object as its "file."
    p = canvas.Canvas(response)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()
    return response

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

  • A resposta HTTP tem um tipo MIME especial, application/pdf. Isso indica ao browser que o documento é um arquivo PDF, ao invés de arquivo HTML. Se deixar isso de fora, o browser provavelmente irá interpretar o ontúdo como HTML, o qual deve resultar em uma feia, assustadora “sopa de ltrinhas” no browser.

  • A resposta HTTP também tem um cabeçalho adicional Content-Disposition, o qual contém o nome do arquivo PDF. Este nome de arquivo é arbitrário: Chame como quizer. Isso será usado pelo browser na caixa de diálogo “Salvar como…”, etc.

  • O cabeçalho HTTP Content-Disposition começa com attachment; neste exemplo. Isso força o browser a mostrar uma caixa de diálogo perguntando/confirmando como manipular o documento mesmo que exista um padrão definido no computador. Se deixar sem o 'attachment;', os browsers usarão qualquer programa/plugin que estejam configurados para usar com PDF. Aqui como o código se parece:

    Code
    response['Content-Disposition'] = 'filename="somefilename.pdf"'
    
  • Acessar a API do ReportLab é fácil: apenas passe o response como primeiro argumento para canvas.Canvas`. A classe ``Canvas espera um objeto “file-like”, e os objetos HttpResponse se encaixam na definição.

  • Note que todos os métodos subsequentes para geração do PDF são chamados a partir do objeto (neste caso , p) – e não do response.

  • E finalmente, é importante chamar showPage() e o save() no arquivo PDF.

PDFs complexosLink para este cabeçalho

Se estiver contruindo documentos PDFs complexos com o ReportLab, considere usar a bilioteca io como um lucar temporário de armazenamento do seu arquivo PDF. Essa biblioteca fornece uma objeto “file-like” como interface que é particularmente eficiente. Aqui o mesmo exemplo “Hello World” de antes, reescrito com uso do io:

Code
from io import BytesIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

    buffer = BytesIO()

    # Create the PDF object, using the BytesIO object as its "file."
    p = canvas.Canvas(buffer)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly.
    p.showPage()
    p.save()

    # Get the value of the BytesIO buffer and write it to the response.
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

Outras fontesLink para este cabeçalho

  • PDFlib é uma outra bibliotea de geração de PDF que tem API, ou “bindings” para Python. Para usá-lo com o Django, apenas use os mesmos conceitos explanados neste artigo.

  • XHTML2PDF é ainda uma outra biblioteca para gerar PDF. Ele vêm com um exemplo de como integrá-lo com o Django.

  • HTMLdoc é um script para a linha de comando que pode converter HTML para PDF. Ele nao tem uma interface para Python. Mas você pode usá-lo acessando o “shell” através do system ou popen e retornar a saída para o Python.

Outros FormatosLink para este cabeçalho

Note que não tem muito nestes exemplos que seja especificamente sobre PDF – apenas as partes usando reportlab. Você pode usar técnicas similares para gerar qualquer outro formato arbitrário para a qual você encontre uma bilioteca Python. Veja também Emitindo CSV com Django para outro exemplo e algumas técnicas que você pode usar quando quiser gerar fomatos baseados em texto.