6

I'm using the Weasyprint library for Python in an attempt to print out an html file to pdf. I am attempting to embed an image into the background of my page. Here is the code:

HTML(string='''
    <h1>The title</h1>
    <p>Content goes here
''', base_url=os.path.dirname(os.path.realpath(__file__))).write_pdf("hello.pdf",  stylesheets=[CSS(string='body{background-image: url("example_image.png")}')])

The output I get to this code is the following:

Ignored `background-image: url("example_image.png")` at 1:6, Relative URI reference without a base URI: 'example_image.png'.
blah@blah:~/Dropbox/Terraverde/annual_reports$ python3 test_excel.py

I have tried to search Stackoverflow for solutions to this problem, and have read the documentation, but the closest thing I could find to an answer is the following post regarding an identical problem but for Django: Django WeasyPrint CSS integration warning: Relative URI reference without a base URI: <link href="/static/css/bootstrap.min.css"> at line None

I also tried using document.baseURI in my code:

base_url=os.path.dirname(os.path.realpath(__file__))).write_pdf("hello.pdf",  stylesheets=[CSS(string='body{background-image: url(document.baseURI + "example_image.png")}')])

but this still yielded an error:

Parse error at 1:24, unexpected BAD_URI token in property value

Any suggestions on how to handle a problem, or perhaps a command similar to Django's request.build_absolute_uri() for either regular Python or for Flask?

Community
  • 1
  • 1
user3787027
  • 61
  • 1
  • 3

2 Answers2

7

I had the same error I had this tag, on OSX, in a template that I rendered with pystache:

<img src="/Users/my_username/my_project/my_image.png" />

So I tried this instead and it worked:

<img src="file:///Users/my_username/my_project/my_image.png" />

Just add file:// before the /Users/... path. (Note that it's 3 slashes).

hendrixski
  • 1,124
  • 1
  • 12
  • 20
3

I figured out that base_url had to be given as an arg to the weasyprint.CSS function and not to the weasyprint.HTML one:

from weasyprint import HTML, CSS

html_content = '''<h1>The title</h1><p>Content goes here'''

base_url = os.path.dirname(os.path.realpath(__file__))
css = CSS(string='body{background-image: url("example_image.png")}', base_url=base_url)

HTML(string=html_content).write_pdf("hello.pdf", stylesheets=[css])

As a bonus, the same with loading local fonts located in a fonts folder placed aside this script:

# for debugging
import logging
logger = logging.getLogger('weasyprint')
logger.addHandler(logging.StreamHandler())

import os

from weasyprint import HTML, CSS
from weasyprint.fonts import FontConfiguration


html_content = '''<h1>The title</h1><p>Content goes here</p>'''

font_config = FontConfiguration()

THIS_FILE_DIR = os.path.dirname(os.path.abspath(__file__)) + os.sep
base_url = 'file://' + THIS_FILE_DIR

# fonts downloaded from
# https://fonts.google.com/specimen/Poppins?preview.text_type=custom&sidebar.open=true&selection.family=Poppins:wght@400;500;600;700
css = CSS(string='''
        @font-face {
          font-family: 'Poppins';
          src: url('./fonts/Poppins-Regular.ttf') format('truetype');
          font-weight: 400;
          font-style: normal;
        }
        
        @font-face {
          font-family: 'Poppins';
          src: url('./fonts/Poppins-Medium.ttf') format('truetype');
          font-weight: 500;
          font-style: normal;
        }
        
        @font-face {
          font-family: 'Poppins';
          src: url('./fonts/Poppins-SemiBold.ttf') format('truetype');
          font-weight: 600;
          font-style: normal;
        }
        
        @font-face {
          font-family: 'Poppins';
          src: url('../base/fonts/Poppins-Bold.ttf') format('truetype');
          font-weight: 700;
          font-style: normal;
        }
        ''', font_config=font_config, base_url=base_url)

HTML(string=html_content).write_pdf("hello.pdf", stylesheets=[css])
fallino
  • 1,381
  • 11
  • 9