25

I am trying to output PDF on Django using the Weasyprint library, but the images don't appear on the generated PDF. I have tried both relative and static URLs for the images, but even the static URL doesn't show the image. When opening the HTML itself on chrome, the images do show.

Here is my pdf generation view in the views.py file:

def pdf_generation(request, some_slug)
    stud = Student.objects.get(some_slug=some_slug)
    studid = stud.some_slug
    context = {'studid':studid}
    html_string = render_to_string('templates/pdf_gen.html', context)
    html = HTML(string=html_string)
    pdf = html.write_pdf(stylesheets=[CSS(settings.STATIC_ROOT +  '/css/detail_pdf_gen.css')]);
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = 'inline; filename="mypdf.pdf"'
    return response

Here is the part of the HTML of the image:

<DIV id="p1dimg1">
<IMG src="{% static 'img/image.jpg' %}" alt="">
</DIV>

And the CSS:

#page_1 #p1dimg1 {position:absolute;top:0px;left:0px;z-
index:-1;width:792px;height:1111px;}
#page_1 #p1dimg1 #p1img1 {width:792px;height:1111px;}

Thank you very much

선풍기
  • 891
  • 1
  • 7
  • 11

5 Answers5

46

Fixed by:

Add base_url=request.build_absolute_uri() so that

html = HTML(string=html_string)

becomes

html = HTML(string=html_string, base_url=request.build_absolute_uri())

That will allow for relative URLs in the HTML file.

For the images, only PNG images seems to work for some reason.

For the HTML styles to show on the PDF, add presentational_hints=True as per the Weasyprint docs:

    pdf = html.write_pdf(stylesheets=[CSS(settings.STATIC_ROOT +  '/css/detail_pdf_gen.css')], presentational_hints=True);
선풍기
  • 891
  • 1
  • 7
  • 11
8

Setup static for the path of your image as:

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

and then you have to pass the base_url in HTML class of Weasyprint as:

HTML(string=html_string, base_url=request.build_absolute_uri())
Abdul Rehman
  • 5,326
  • 9
  • 77
  • 150
6

After adding HTML(string=html_string, base_url=request.build_absolute_uri()) to my config images were still not loading. Had to use below logging to identify real issue.

import logging
logger = logging.getLogger('weasyprint')
logger.addHandler(logging.FileHandler('/tmp/weasyprint.log'))

Then check /tmp/weasyprint.log log file for errors.

Real issue for me was:

urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate

Fix was to disable ssl verification:

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
Jonny
  • 314
  • 4
  • 6
  • all mentioned answers above were not successful. this one helped out to see that I can also use external CSS without having to use `stylesheets=[CSS(...)]` – Nwawel A Iroume Sep 20 '22 at 05:06
0

I don't know Weasyprint, but I'm using Pisa and it works very well with pictures into PDF output.

For example :

def PDFGeneration(request) :

    var1 = Table1.objects.last()
    var2 = Table2.objects.last()

    data = {"key1" : variable1, "key2" : variable2}

    html = get_template('My_template_raw.html').render(data)
    result = StringIO()

    with open(path, "w+b") as file :
      pdf = pisa.pisaDocument(StringIO(html), file, link_callback=link_callback)
      file.close()

      image_data = open(path, "rb").read()
      return HttpResponse(image_data, content_type="application/pdf")

    return render(request, 'HTML template', context)

and

def link_callback(uri, rel):
    if uri.find('chart.apis.google.com') != -1:
        return uri
    return os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))

My PDF is generated from an .html file and I have my picture like this :

<html>
    <head>
    {% load staticfiles %}
    {% load static %}

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   
    <link rel="stylesheet" type="text/css" href="{% static 'css/MyFile.css' %}"/>

    <style>

            body {
                font-family: Courier New, Courier, monospace;
                text-align: justify;
                list-style-type: none;
            }
    </style>

    </head>

    <body>

        <img src="{{MEDIA_ROOT}}Logo/logo.jpeg" width="250" height="66"/>
        <br></br>
        ...
Essex
  • 6,042
  • 11
  • 67
  • 139
  • I was meddling with the code until I had some serious doubts about myself and tried other pictures and it seems only png images are showing. Maybe it's the css that is wrong or I might just have to convert all images to png. Thanks for the answer though! – 선풍기 Feb 26 '18 at 13:29
  • Ok. It's weird, but one year ago, I was searchng a good way to obtain PDF with pictures and `Pisa` with `html2pdf` seems to be the best tool to do that ;) I don't have any issue and it works fine. If my answer helped you, don't hesitate to vote up. – Essex Feb 26 '18 at 13:32
0

I was having this problem. I added "base_url='base_url'" to the following line and it finally worked.

html = weasyprint.HTML(string=rendered_string, base_url='base_url')

Attaching pic of my code for context.weasyprint project rendering image now