Creating Dynamic PDF reports using Jinja and Gotenberg

I use Jinja2 in a variety of ways. Sometimes to create SVGs and other times to create reports. Recently there was a requirement to create PDF reports as part of a service. Since the app already uses Python and Jinja2, we used that to generate PDF reports. Using data and Jinja2, we created the HTML report that's step 1. In step 2, we wanted to convert the HTML reports into PDFs. There are many options in Python for that, like wkhtmltopdfxhtml2pdf, or the standard Chrome browser print feature. 

But for a while, the team has been using Gotenberg. And it's been very stable and has met all our expectations. It has a developer-friendly API for converting numerous document formats into PDF files and more! 

So we did just that. We embedded CSS, JS, base64 image and fonts, and SVG inside `index.html` to make it simple and self-contained. It worked out very well. 

You can also set up a webhook in case you don't want to wait till the Gotenberg generates the PDF.

import requests

# This can be a standard jinja2 rendering. 
# Here I am using standard formatter.
# Use what works
template = """       
            <html>
            <style>
                .h {{
                  padding: 60px;
                  text-align: center;
                  background: #1abc9c;
                  color: white;
                  font-size: 30px;
                }}
            </style>
            <body>
            <h1 class="h"> {header} </h1>
            Welcome to my awesome world.
            </body>
        </html> """
content = template.format(header="Hello, World!")

# Headers
headers = {
   
}


# I am embedding everything, like CSS, JS, base64 image, SVG inside `index.html`
# So I just have to send one file.
# gotenberg expects the file to be called `index.html` and hence

files = {
    'file': ('index.html', content, 'text/html'), 
}

server = "https://demo.gotenberg.dev/forms/chromium/convert/html"
#server = "https://httpbin.org/post"

response = requests.post(server, headers=headers,files=files)
print(response)

#response.content is the pdf content, you can write it to a file or send it anywhere

with open('test.pdf', 'wb') as f:
    f.write(response.content)

You can read this blog using RSS Feed. But if you are the person who loves getting emails, then you can join my readers by signing up.

Join 2,242 other subscribers

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.