Skip to content

Instantly share code, notes, and snippets.

@blakebjorn
Created March 9, 2018 15:38
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save blakebjorn/de24417bb032c71c3901a82c79bcf926 to your computer and use it in GitHub Desktop.
Save blakebjorn/de24417bb032c71c3901a82c79bcf926 to your computer and use it in GitHub Desktop.
pdf generation with jinja2 and html
import pandas as pd
import jinja2
import pdfkit
from random import getrandbits, randint
# pdfkit is just a wrapper for whktmltopdf. you need to install wkhtml and have it on the path
# alternatively, you can move wkhtmltoimage.exe, wkhtmltopdf.exe and wkhtmltox.dll into the working directory
# Create some data
def random_hex(length=10):
return '%0x' % getrandbits(length * 4)
df = pd.DataFrame([{"number":randint(0,100),
"name":random_hex(15),
"data1":random_hex(5),
"data2":random_hex(5),
"data3":random_hex(5)} for i in range(10)])[['number','name','data1','data2','data3']]
# Don't include the dataframe index in the html output,
# add the appropriate css class, and don't draw the border.
dfhtml = df.to_html(index=False, classes="table-title", border=False)
# Load the template
env = jinja2.Environment(loader=jinja2.FileSystemLoader("."))
template = env.get_template("tableTemplate.html")
# pass df, title, message to the template.
html_out = template.render(df=dfhtml,
title="Jinja2 Example",
message="This is an example text input")
# write the html to file
with open("output.html", 'wb') as file_:
file_.write(html_out.encode("utf-8"))
# write the pdf to file
pdfkit.from_string(html_out, output_path="output.pdf", css=["template.css"])
<link rel="stylesheet" type="text/css" href="template.css"/>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>{{title}}</title>
<meta name="viewport" content="initial-scale=1.0; maximum-scale=1.0; width=device-width;">
</head>
<body>
<div class="table-title" align="center">
<h4>{{ title }}</h4>
<p style="font-weight: bold">templating example.</p>
</div>
<div align="center">
{{ df }}
</div>
<p align="center">{{ message }}</p>
</body>
</html>
/*** Most of this CSS is unused in the exaple **/
@import url(https://fonts.googleapis.com/css?family=Roboto:400,500,700,300,100);
body {
background-color: #ffffff;
font-family: "Roboto", helvetica, arial, sans-serif;
font-size: 22px;
font-weight: 400;
text-rendering: optimizeLegibility;
}
h4 {
margin-bottom: 0px;
margin-top: 5px;
}
hr {
height:2px;
visibility:hidden;
line-spacing:0px;
}
div.table-title {
display: block;
margin: auto;
max-width: 600px;
padding:5px;
width: 100%;
}
.table-title h3 {
color: #000000;
font-size: 30px;
font-weight: 400;
font-style:normal;
font-family: "Roboto", helvetica, arial, sans-serif;
text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.1);
text-transform:uppercase;
}
/*** Table Styles **/
.table-fill {
background: white;
border-radius:3px;
border-collapse: collapse;
border-bottom:2px solid #C1C3D1;
border-right:2px solid #C1C3D1;
border-left:2px solid #C1C3D1;
height: 320px;
margin: auto;
max-width: 600px;
padding:5px;
width: 100%;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
animation: float 5s infinite;
}
th {
color:#D5DDE5;
background:#1b1e24;
border-bottom:2px solid #1b1e24;
border-top:2px solid #1b1e24;
border-right: 1px solid #343a45;
font-size:23px;
font-weight: 300;
padding:12px;
text-align:left;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
vertical-align:middle;
white-space: pre;
}
th:first-child {
border-top-left-radius:3px;
border-left: 2px solid #1b1e24;
}
th:last-child {
border-top-right-radius:3px;
border-right: 2px solid #1b1e24;
}
tr {
border-top: 1px solid #C1C3D1;
border-bottom-: 1px solid #C1C3D1;
color:#000000; /*#666B85*/
font-size:16px;
font-weight: normal;
text-shadow: 0 1px 1px rgba(256, 256, 256, 0.1);
white-space: pre;
}
tr:hover td {
background:#4E5066;
color:#FFFFFF;
border-top: 1px solid #22262e;
border-bottom: 1px solid #22262e;
}
tr:first-child {
border-top:none;
}
tr:last-child {
border-bottom:none;
}
tr:nth-child(odd) td {
background:#EBEBEB;
}
tr:nth-child(odd):hover td {
background:#4E5066;
}
tr:last-child td:first-child {
border-bottom-left-radius:3px;
}
tr:last-child td:last-child {
border-bottom-right-radius:3px;
}
td {
background:#FFFFFF;
padding:20px;
text-align:left;
vertical-align:middle;
font-weight:450;
font-size:20px;
text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.1);
border-right: 1px solid #C1C3D1;
white-space: nowrap;
}
td:last-child {
border-right: 0px;
}
th.text-left {
text-align: left;
}
th.text-center {
text-align: center;
}
th.text-right {
text-align: right;
}
td.text-left {
text-align: left;
}
td.text-left-top {
vertical-align: top;
text-align: left;
}
td.text-center {
text-align: center;
}
td.text-right {
text-align: right;
}
footer {
page-break-after: always;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment