Kuba
Kuba

Reputation: 433

Attach img file in PDF Django Weasyprint

Hello friends

I want to ask you for help.

I need help with attach img file in pdf we use WeasyPrint for generation pdf from html.

I don't know where to add base_url=request.build_absolute_uri() to tasks.py. Where in the file tasks.py ?

Now instead of images is empty place.

I try my best but i don't succeed. So please help.

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>

tasks.py

from celery import task
from django.shortcuts import get_object_or_404
from oferty.models import Order
from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives
from django.conf import settings
import weasyprint
from weasyprint import default_url_fetcher, HTML
from io import BytesIO

@task
def order_created(order_id):
    """
    Task to send an e-mail notification when an order is successfully created.
    """
    order = Oferta.objects.get(id=order_id)
    subject = 'xxx nr {}'.format(order.id)
    html_content = '<p><strong>Hallow, {}!</p></strong><br><p>
    email = EmailMultiAlternatives(subject,
                                   html_content,'[email protected]',
                                   [order.email])

    # generation PDF.
    html = render_to_string('order/order/pdf.html', {'order': order})
    out = BytesIO()
    stylesheets = [weasyprint.CSS(settings.STATIC_ROOT + 'css/pdf.css')]

    weasyprint.HTML(string=html).write_pdf(out,
                                           stylesheets=stylesheets)
    # attach PDF.
    email.attach('order_{}.pdf'.format(order.id),
                 out.getvalue(),
                 'application/pdf')

    email.attach_alternative(html_content, "text/html")
    email.send()

I would appreciate your help

Upvotes: 3

Views: 4395

Answers (1)

Alex
Alex

Reputation: 1262

I solved this problem by encoding the image in base64 and sending to the template through context, then rendering with CSS. You can put your uri definition just before using HTML

So, my task is like this:

    from django.template.loader import get_template
    from weasyprint import HTML

    with open("path/to/image.png", "rb") as image_file:
        encoded_string = base64.b64encode(image_file.read())               

    context = {..., "img":encoded_string , ...}

    html_template = get_template('my_template_to_PDF.html')  
    html = html_template.render(context).encode(encoding="UTF-8")
    uri = request.build_absolute_uri()
    pdf_file = HTML(string=html,base_url=uri,encoding="UTF-8").write_pdf('path/to/output.pdf')

The template:

<style>
...
div.image {
  width:150px;
  height:50px;
  background-image:url(data:image/png;base64,{{img}});
}
...
</style>
...
<div class = 'image'></div>
...

Hope it helps!

Upvotes: 3

Related Questions