Gerando PDF a partir de HTML no Admin do Django

Aloha Devs!

Gerar PDFs é uma das tarefas mais corriqueiras na vida de um desenvolvedor, trago hoje a vocês uma ótima solução quando se trata de geração de PDFs no django. Mais precisamente no admin do django, sem mais delongas vamos ao que interessa.

Criando o projeto

Antes de tudo precisamos criar o projeto, para isso crie um ambiente virtual com o pipenv (Caso não esteja familiarizado com o pipenv leia esse post onde explico tudinho) e instale o django com:

$ pipenv install django==2.0

Crie o projeto executando o comando abaixo:

$ django-admin.py startproject project .

Crie a aplicação que armazenará toda a nossa lógica com:

$ python manage.py startapp reports

E configure os valores do seu settings como o arquivo abaixo:

Criando o models

Com o settings.py configurado, precisamos agora criar nosso models no arquivo reports/models.py adicione o código abaixo:

Perceba que o models Report é a representação bem simples de um relatório e será ele que armazenará os dados que vamos renderizar no PDF.

Configurando o Admin

Com nosso models pronto, precisamos agora configurar nosso admin, no arquivo reports/admin.py adicione o código abaixo:

De forma bem simples, nosso ReportAdmin cria um CRUD bem simples com o nosso model Report e disponibiliza o mesmo no admin que do django.

Para melhor exemplificar vamos criar um super usuário e visualizar o resultado, para isso execute:

$ python manage.py createsuperuser

Preencha os dados solicitados, e execute:

$ python manage.py runserver

Acesse seu localhost:8000/admin/, realize o login e você terá uma tela como essa:

Na aba Relatórios, você terá uma tela semelhante a essa:

Nosso CRUD está pronto, precisamos agora criar um botão e o método que será chamada e gerará o PDF para nós.

Gerando o PDF

Quando se trata de criação de PDF, temos duas alternativas. A primeira é literalmente ‘desenhar’ através de programação oque queremos que seja exibido no PDF, e a segunda é utilizar a boa e velha casadinha HTML e CSS para facilitar nosso trabalho e termos um design mais rico em nossos documentos.

Utilizaremos aqui a segunda opção, que além de mais fácil, é a mais utilizado hoje em dia. Para isso utilizaremos a biblioteca weasyprint para facilitar nosso trabalho.

Antes de tudo, precisamos intalá-la, para isso execute:

$ pipenv install weasyprint

E por fim criar nosso template HTML que será usado como base para a renderização do PDF.

para isso, crie um diretório template na raiz do projeto e dentro dela crie outro diretório chamado reports que conterá o arquivo pdf_template.html, o caminho será templates/reports/pdf_template.html e adicione o conteúdo abaixo:

Note que nosso template é bem simples, basicamente renderiza as informações que temos em nosso objeto de Report. Lembrando que todo o CSS tem que ser interno, pois ainda não existe a possibilidade de utilizar CSS externo na geração de PDF.

Com tudo pronto, o nosso arquivo reports/admin.py ficará como exibido abaixo:

Indo por partes, oque adiciona-mos além dos imports claro, foi o método generate_pdf(), que recebe a requisição e um objeto que terá suas informações renderizadas no PDF.

Na função render_to_string(), informamos o template html que será usado como base para o PDF e passamos o contexto para o template com o objeto que recebemos acima.

Criamos uma instância da classe HTML onde se recebe uma string que é o resultado da função acima e por fim executamos o método write_pdf() da classe HTML passando um target para a mesma.

Por fim, usando o módulo de FileSystem do python, salvamos o arquivo e retornamos o response.

Criando uma Action no admin do django

Para executar esse método precisamos criar uma Action no django. Porém, diferentemente das actions que o django já disponibiliza, criaremos uma action que será atrelada a um objeto em questão, ou seja, cada objeto registrado no nosso banco contará com uma action que só atuará sobre ela.

Para facilitar nosso trabalho, utilizaremos a biblioteca django-object-actions. Para isso precisamos instalá-la com o comando abaixo:

$ pipenv install django-object-actions

E adicionar o ‘django_objects_actions’ nos INSTALLED_APPS como é mostrado abaixo:

Finalizado a instalação, tudo que precisamos fazer é importar a classe DjangoObjectActions e passa-la como herança para a classe ReportAdmin como é mostrado abaixo:

Por fim tribuimos um label que será o texto exibido no botão, um short_description que será o texto que aparece quando passamos o ponteiro do mouse sobre o botão, e o change_actions() que recebe o método que será chamado quando clicar-mos no botão, simples né? Lembrando que se tivessemos outros métodos, era só criar o label e o short_description para cada método e passálo dentro da tupla do change_actions().

O resultado disso você pode conferir criando um relatório e acessando o mesmo, note que aparecerá um novo botão ao lado do botão histórico como é mostrado na imagem abaixo:

Tudo pronto, basta clicar no botão gerar PDF e a mágica acontecerá.

❤ Gostou? Vamos espalhá-lo — curte e compartilha aí o/