Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a PDF with a given template, with dynamic data in Python or NodeJS to be deployed on AWS

Looking for recommendation of a library in Python(first preference) or NodeJS that can generate a pdf file preferably from dynamic html template to be run in AWS. Requirement is to generate invoice pdf to be sent to customers.

Have come across below 2 Node libraries:

  • PDFKit
  • jsPDF

Here we might have to deal with numbers for X and Y.

Better approach would be something where we can simply use html/css to generate template with placeholders which can be replaced with dynamic data(coming from database query). Any suggestions would be appreciated.

Thanks!

like image 765
bijalcm Avatar asked Dec 02 '19 07:12

bijalcm


1 Answers

This approach worked for me in Python using below libraries:

Jinja2 - for generating HTML with custom data

xhtml2pdf - for generating PDF from HTML

Consider within your PROJECT DIR, there is a template file(invoice.html) and python file(pdf_generator.py)

pdf_generator.py

from xhtml2pdf import pisa 
import jinja2
templateLoader = jinja2.FileSystemLoader(searchpath="./")
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "invoice.html"
template = templateEnv.get_template(TEMPLATE_FILE)

# This data can come from database query
body = {
    "data":{
        "order_id": 123,
        "order_creation_date": "2020-01-01 14:14:52",
        "company_name": "Test Company",
        "city": "Mumbai",
        "state": "MH",
    }
}

# This renders template with dynamic data 
sourceHtml = template.render(json_data=body["data"]) 
outputFilename = "invoice.pdf"

# Utility function
def convertHtmlToPdf(sourceHtml, outputFilename):
    # open output file for writing (truncated binary)
    resultFile = open(outputFilename, "w+b")

    # convert HTML to PDF
    pisaStatus = pisa.CreatePDF(
            src=sourceHtml,            # the HTML to convert
            dest=resultFile)           # file handle to receive result

    # close output file
    resultFile.close()

    # return True on success and False on errors
    print(pisaStatus.err, type(pisaStatus.err))
    return pisaStatus.err

if __name__ == "__main__":
    pisa.showLogging()
    convertHtmlToPdf(sourceHtml, outputFilename)

invoice.html

<!DOCTYPE html>
<html lang="en">
<body>
Name: {{ json_data.company_name }} <br>
City/State: {{ json_data.city }}, {{ json_data.state }} <br>
Date: {{ json_data.order_creation_date }} <br>
Order ID: {{ json_data.order_id }} <br>
</body>
</html>
like image 183
bijalcm Avatar answered Oct 30 '22 16:10

bijalcm