Search code examples
pythonjinja2weasyprint

Render image in template.html with Jinja2 and weasyprint in a PDF


I have a python file that generates an HTML page (and a PDF) using jinja2 like this.

import pandas as pd
import requests
from jinja2 import Environment, FileSystemLoader
from weasyprint import HTML

# Stuff to get dataframe...

# Generate PDF and csv
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template("template.html")

template_vars = {"title" : "Something...",
                "vulnerabilities_table": df.to_html(index=False)}

html_out = template.render(template_vars)
HTML(string=html_out).write_pdf("report_styled.pdf", stylesheets=["style.css"])

It uses the following template.html

<!DOCTYPE html>
{% block layout_style %}
<style> @page { size: letter landscape; margin: 2cm; } </style>

{% endblock %}
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>{{ title }}</title>
</head>
<body>
    <img src="static/images/Logo.png" style="height: 100; width: 300; float:inline-start">
    <h2>{{ title }}</h2>
     {{ vulnerabilities_table }}
</body>
</html>

The problem is that the image is not rendering at all (but the rest does). I guess it's because I'm not using Flask

<img src="static/images/Logo.png" style="height: 100; width: 300; float:inline-start">

My image is in the folder static/images/Logo.png. What did I do wrong ?


Solution

  • The problem is not about Flask. It's about weasyprint converting html page (it's actually html string in your case) to PDF. For weasyprint HTML class to fetch the img source (static/images/Logo.png), you need to put the full local file path as file:///path/to/folder/static/images/Logo/png.

    What you can do is, in template.html:

    <img src="{{ image_path }}" style="height: 100; width: 300; float:inline-start">
    

    In python code:

    import os
    this_folder = os.path.dirname(os.path.abspath(__file__))
    template_vars = {"title" : "Something...",
                    "vulnerabilities_table": "hello world",
                     "image_path": 'file://' + os.path.join(this_folder, 'static', 'images', 'Logo.png' )}
    html_out = template.render(template_vars)
    HTML(string=html_out).write_pdf("report_styled.pdf", stylesheets=["style.css"])