Automate Invoice Generation with Python and Jinja2
Generating invoices manually can be time-consuming and error-prone—especially for freelancers or small businesses juggling multiple clients. With Python and Jinja2, you can turn structured data into professional PDF invoices in just a few lines of code. In this guide, we’ll walk through automating invoice generation using Python, JSON input, Jinja2 templating, and a tool to convert HTML to PDF.
1. Project Setup and Dependencies
To get started, make sure you have Python 3 installed. Then install the required packages:
pip install jinja2 pdfkit
We’ll also need wkhtmltopdf, an external tool that renders HTML to PDF. On most systems you can install it via:
# macOS
brew install wkhtmltopdf
# Ubuntu/Debian
sudo apt install wkhtmltopdf
Once installed, Python will use the wkhtmltopdf binary internally through the pdfkit
library.
2. Structuring Your Invoice Data
Let’s define how our invoice data will look. We’ll assume it’s in JSON format and includes items like customer name, invoice number, line items, and totals. Here’s a sample structure:
{
"invoice_number": "INV-001",
"date": "2024-06-15",
"client": {
"name": "Acme Corp",
"address": "123 Main St, Metropolis, USA"
},
"items": [
{ "description": "Web development", "hours": 10, "rate": 50 },
{ "description": "Consulting", "hours": 5, "rate": 80 }
]
}
This structure allows easy expansion—adding tax fields, logo, etc. later.
3. Building the HTML Template with Jinja2
Jinja2 enables dynamic templating using familiar syntax. Create a file called invoice_template.html
:
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.header { text-align: center; margin-bottom: 40px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px; border: 1px solid #ccc; }
</style>
</head>
<body>
<div class="header">
<h1>Invoice {{ invoice_number }}</h1>
<p>Date: {{ date }}</p>
</div>
<p><strong>Bill To:</strong> {{ client.name }}<br>{{ client.address }}</p>
<table>
<tr><th>Description</th><th>Hours</th><th>Rate</th><th>Amount</th></tr>
{% for item in items %}
<tr>
<td>{{ item.description }}</td>
<td>{{ item.hours }}</td>
<td>${{ item.rate }}</td>
<td>${{ item.hours * item.rate }}</td>
</tr>
{% endfor %}
</table>
<p><strong>Total: ${{ items | sum(attribute='hours') | float * items | sum(attribute='rate') | float }}</strong></p>
</body>
</html>
This HTML template dynamically loops through line items, calculates totals, and injects data fields into the layout.
4. Generating PDF Invoices from JSON
Now let’s write the Python script that loads your data, renders the HTML, and converts it to PDF.
import json
import pdfkit
from jinja2 import Environment, FileSystemLoader
# Load data
with open('invoice_data.json') as f:
data = json.load(f)
# Set up Jinja2 environment
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('invoice_template.html')
# Render template
rendered_html = template.render(**data)
# Export to PDF
pdfkit.from_string(rendered_html, 'invoice_output.pdf')
This script takes your JSON invoice input, injects it into the Jinja2 HTML, and calls pdfkit.from_string
to create a valid PDF file.
5. Tips for Production-Grade Usage
As you scale or enhance this automation, keep in mind the following tips:
- Validate JSON Input: Use schemas or libraries like
pydantic
to ensure data correctness and prevent invalid inputs. - Use HTML Partials: Break your template into headers/footers/partials for reusability.
- Batch Generation: Loop through multiple JSON files to generate all invoices in one batch.
- Add Styles: Enhance visual appeal by styling your HTML with CSS or using frameworks like Bootstrap.
- Security Considerations: Only render trusted templates if running this server-side to avoid SSRF/XSS exploits.
Performance-wise, this method is efficient for small to medium volumes. For large-scale invoice processing systems, consider generating PDFs asynchronously using task queues like Celery.
Conclusion
Automating invoice generation with Python and Jinja2 saves you time, reduces mistakes, and improves client professionalism. Whether you’re a freelancer invoicing weekly or a growing business, integrating this process into your workflows can pay off quickly. With just a few tools—Python, Jinja2, and pdfkit—you can produce beautiful invoices, powered directly from your data.
Useful links: