[Solved]-Attach img file in pdf weasyprint

15πŸ‘

βœ…

use static for path of the image file

  {% load static %}
    <img src="{% static 'images/static.jpg' %}" alt="">

and pass base_url in HTML class in views.py

pdf_file = HTML(string=rendered_html, base_url=request.build_absolute_uri())

html file

<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <img src="{% static 'images/static.jpg' %}" alt="">
    </div>
</body>
</html>

views.py

from django.template.loader import get_template
from weasyprint import HTML, CSS
from django.conf import settings
from django.http import HttpResponse


def generate_pdf(request):
    html_template = get_template('latest/html_pdf.html')
    user = request.user
    rendered_html = html_template.render().encode(encoding="UTF-8")
    pdf_file = HTML(string=rendered_html, base_url=request.build_absolute_uri()).write_pdf(stylesheets=[CSS(settings.STATIC_ROOT +  '/css/generate_html.css')])



    http_response = HttpResponse(pdf_file, content_type='application/pdf')
    http_response['Content-Disposition'] = 'filename="generate_html.pdf"'

    return http_response
πŸ‘€Thameem

1πŸ‘

In case of sending emails with pdf attached, it’s possible to pass path from view to function dedicated to emails.
views.py

[...]
path = request.build_absolute_uri()          # build absolute path
order_confirmation.delay(order.id, path)     # pass to func
[...]

tasks.py

@app.task
def order_confirmation(order_id, path):       # receive path
    order = Order.objects.get(id=order_id)
    subject = f"Order nr. {order.id}"
    email_from = settings.EMAIL
    email_to = order.get_email
    message = (...)
    email = EmailMessage(subject, message, email_from, [email_to])
    html = render_to_string('pdf.html', {'order' : order, 'company': company})
    out = BytesIO()
    stylesheets=[weasyprint.CSS(settings.STATIC_ROOT + '/css/pdf.css')]
    weasyprint.HTML(string=html, base_url=path).write_pdf(out, stylesheets=stylesheets)      # use here
    email.attach(f'order_{order.id}.pdf',
        out.getvalue(),
        'application/pdf')
    email.send()

πŸ‘€ImustAdmit

0πŸ‘

If the file and pdf generation occurs on your disk, link base_url to your directory:

base_url = os.path.dirname(os.path.realpath(__file__))
HTML(string=html_template, base_url=base_url).write_pdf(pdf_filename)

A simple working example, with on-the-fly generation of a bar chart png, and insertion into the html / pdf:

import os

import matplotlib.pyplot as plt
import pandas as pd
from weasyprint import HTML

# Table to plot
data = {"Exam Name": ["Exam 1", "Exam 2", "Exam 3"], "Result": ["Pass", "Fail", "Pass"]}
df = pd.DataFrame(data)

# Data series to plot
series = pd.Series([1, 2, 3, 3])
plt.figure(figsize=(8, 6))
series.plot(kind="bar", x="Exam Name", y="Result", legend=False)
plt.title("Exam Results")
plt.xlabel("Exam Name")
plt.ylabel("Result")
plt.xticks(rotation=0)
plt.savefig("bar_plot.png", bbox_inches="tight")

html_template = f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        {df.to_html(index=False, classes='table')}
        <img src="bar_plot.png" alt="">
    </div>
</body>
</html>
"""

# Generate the PDF from the HTML template
pdf_filename = "report.pdf"

base_url = os.path.dirname(os.path.realpath(__file__))
HTML(string=html_template, base_url=base_url).write_pdf(pdf_filename)

It gives:
enter image description here

πŸ‘€PJ127

Leave a comment