Trouble with xhtml2pdf failing to render CSS when converting HTML to PDF

Conversion:

html = template.render(context)
resultFile = open(filepath, "w+b")
pdf = pisa.CreatePDF(html.encode('utf-8'), dest=resultFile,encoding='utf-8', link_callback=link_callback)

link_callback

def link_callback(uri, rel):
    sUrl = settings.STATIC_URL      # Usually /static/
    sRoot = settings.STATIC_ROOT    
    mUrl = settings.MEDIA_URL       # Usually /static/media/
    mRoot = settings.MEDIA_ROOT     # Typically /home/userX/project_static/media/

    # Convert URIs to absolute system paths
    if uri.startswith(mUrl):
        path = os.path.join(mRoot, uri.replace(mUrl, ""))
    elif uri.startswith(sUrl):
        path = os.path.join(sRoot, uri.replace(sUrl, ""))
    else:
        return uri  # handle absolute uri (ie: http://some.tld/foo.png)

    # Ensure that file exists
    if not os.path.isfile(path):
        raise Exception(
            'media URI must start with %s or %s' % (sUrl, mUrl)
        )
    return path

I successfully generated a pdf using xhtml2pdf. The file was created, but unfortunately, the css styles are not being applied correctly. I verified the path returned from link_callback and it is accurate, however, the pdf does not display any css styling.

css:

#page_1 {position:relative; overflow: hidden;margin: 64px 0px 65px 0px;padding: 0px;border: none;}

#page_1 #p1dimg1 {position:absolute;top:0px;left:20%;z-index:-1;width:600px;height:870px;}
#page_1 #p1dimg1 #p1img1 {width:600px;height:870px;}

#page_2 {position:relative; overflow: hidden;padding-left: 100px;border: none;height: 854px;}

#page_2 #p2dimg1 {position:absolute;left:27%;z-index:-1;width:490px;height:669px;}
#page_2 #p2dimg1 #p2img1 {width:490px;height:669px;}

The css path obtained: /Users/mypc/project/project/static/css/lender_borrower.css

Answer №1

If you're using xhtml2pdf, remember that external stylesheets cannot be linked to.

To style your PDF document, you'll need to include an internal style sheet within the HTML template itself. This means placing your CSS styles between the

<style type="text/css"></style>
tags in the head section.

It's important to note that not all CSS properties are supported by xhtml2pdf. Refer to the documentation for a list of supported CSS properties.

Here is a sample template structure:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8>
  <title>Your Title Here</title>
  <style type="text/css">

  # PLACE YOUR CSS STYLES HERE

  </style>
</head>
<body>

# Your content goes here

</body>
</html>

Answer №2

When it comes to loading images, backgrounds, and stylesheets from an HTML document in xhtml2pdf, the default expectation is that these files are located on the local drive. However, there are instances where a programmer may need to load these resources from different sources such as via HTTP requests from the Internet or even from a database. In order to facilitate this, a link_callback can be defined to handle such requests.

The documentation suggests that external style sheets can indeed be added using the link_callback function, although the process of doing so is unclear to me. Is there anyone who can provide assistance with this? Specifically, I am looking for guidance on how to load static files in Django.

Answer №3

By the year 2024, it is possible to integrate an external stylesheet by following this method:

Example input file:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Assurance Report</title>
    <link rel="stylesheet" type="text/css" href="Styles\assuranceReport.css" />
</head>
<body>
...

Python scripting (for Windows):

from xhtml2pdf import pisa

with open('Docs\\assuranceReport.html', 'r') as input_file:
    source_html = input_file.read()
    result_file = open("My.pdf", "w+b")

    pisa_status = pisa.CreatePDF(
                source_html,
                #default_css - no need for anything here
                dest=result_file)

        result_file.close()
        # return False on success and True on errors
        return pisa_status.err

An important note is that the CSS file must be saved in UTF-8 format rather than UTF-8-BOM to avoid parsing issues with xhtml2pdf:

https://i.sstatic.net/larbR.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Achieving a consistent fixed width for tbody even when scrollbar is present

thead{ width: calc(100% - 17px); display:block; } tbody{ display:block; overflow-y: auto; height:100px; } http://jsfiddle.net/mkgBx/ Is there a way to adjust the width of the tbody element to match that of the thead element plus the scrollbar? Currently ...

What are some strategies for creating a smooth transition with a max-height of 0 for a single-line div?

I have a div that is one "line" in height. When a button is clicked, I want it to disappear and simultaneously another div with more lines should appear. I have managed to make this work, but no matter what I do, the one-line div disappears very quickly al ...

Where are Temporary files stored in the Google Chrome extension?

I've been searching for over 3 hours, but still cannot locate the exact location (under OS X 10.6.8). Utilizing PageSpeed Insights, I am attempting to find where temporary compressed images are stored. The Chrome "web" location displayed is: filesy ...

Tips on storing the amount of time a user devotes to answering questions on my form into a database

I am facing an issue with storing the "duration" in my database. The "duration" I aim to store is the time spent by the user answering a question I created. When they click the submit button, I want to save the duration they spent in the database. Below i ...

Tips on how to maintain the value of an integer variable even after clicking a submit button, enabling its reuse on the same page

Take a look at the first part of this code where we are using the variable $Tno. if(isset($_POST['submit'])) { $Tno=$_POST['Tno']; $query="SELECT * FROM docs WHERE Tno='$Tno'"; $result=mysql_query($query) or di ...

Unable to remove Css class through code behind

I'm currently working on a Gridview code snippet: <SelectedRowStyle CssClass="SelectedRowStyle" /> This changes the color of the selected row to yellow. However, when I click a button, I want to remove the css class. I attempted to do this in ...

How can the 'One' table be made optional in a One-to-Many relationship within Django?

I am facing a challenge with my app that involves two tables: Anonym and Userdatabase. My goal is to make the app function without requiring users to log in, utilizing only the deviceid of the user to process account information through Anonym. However, if ...

Creating a dynamic workspace with a portable viewing window

I am looking to create a spacious workspace for arranging objects, but I also want to incorporate a customizable "viewport" that will display a specific area of the workspace for the user. This viewport should be resizable and movable within the workspace, ...

Leveraging Font Awesome and Material Icons within ngFor in Angular 2

I have a unique situation where I need to display a dynamic list of icons in a right side bar. These icons are added to the sidebar based on user actions and are displayed using the ngFor directive. The challenge here is that some icons come from Font Awe ...

Unable to view image when using material-ui CardMedia component

Hello, I've encountered a problem with rendering an image in my application. Let me explain the issue in a simplified manner. So, I have a card component (MyCardComponent) where I need to pass a string prop containing the image file location. The goa ...

Hover causing opacity problem in CSS

Check out my code snippet on JSFiddle: http://jsfiddle.net/Vbtts/2624/ Here is the HTML structure: <a href="#" class="col-xs-6 col-sm-4 big-container with-background"> <div class="bottom-align"> <label class="upperca ...

Tips for avoiding the display of concealed forms on a webpage

Hey there, I'm just starting out with html forms and currently experimenting with Jquery to hide forms upon loading the page. However, I've encountered an issue where some forms briefly appear before hiding after the page finishes loading. Here& ...

New jQuery div elements do not have animations when using $(document).on

After creating an animation function that worked well with hovering over squares and leaving a trail, I later needed to add or remove squares based on the page size. Seeking help from here, I discovered my bind animation function wouldn't work on new ...

Showing videos on Django Template: Link to Media

Struggling to retrieve a video from a model as the correct URL is not being found even after adding the media directory in front of it. Is the method I am using to pull the URL from the model accurate? Check out the Code, Generated HTML, and Console log ...

Getting started with a Django app is simple and straightforward. Ready to

Recently, I decided to explore using django-ios-notifications for sending PUSH notifications via APNS (https://github.com/stephenmuss/django-ios-notifications), despite having no prior experience with Django. Although I diligently followed the instructions ...

Explore the Filter List without being affected by the arrangement of words or the level of search precision

I was able to resolve the issue by adjusting my search filter algorithm. Now, I can search regardless of word order, but the results are not as specific as I need them to be. When I type "Correy" in the search bar, it shows all results containing that wo ...

A guide on updating a boolean field in the database using ajax

Here is a piece of my html code: <form action="" method="post"> {% csrf_token %} {% if donate.is_taken == False %} <br> <button type="submit" class="btn" name="taken_or_not" ...

Troubles with Flex wrap in CSS3 on iOS 10.3.2 browsers (Chrome and Safari)

Before sending me to other similar questions, keep in mind that I have already gone through them, attempted the solutions, and they are not resolving my issue. The problem I am encountering involves the flexbox layout. I am using the flexbox layout for ce ...

Creating a moving background for a loading bar with HTML5 and Shadow DOM is currently underway

Can anyone help with animating the progress bar using the HTML5 <progess> tag? I've been able to customize the Shadow DOM elements successfully, but I'm having trouble animating the background (repeating linear gradient). It seems to work i ...

ng-click event not firing after $compile in AngularJS

I'm struggling to get my dynamic HTML elements generated from an AngularJS controller to trigger a function using ng-click. Even after using $compile, the function is not being called. Check out my JS code: var accountApp = angular.module('acco ...