Bootstrap 不渲染

Car*_*cco 6 python pdf pdfkit flask python-3.x

问题分为不同部分:

  • 小序言和尝试分享
  • 重现问题的文件夹结构和代码
  • 显示和解释问题
  • 问题

前言

我在 Raspbian 上使用 Python 3.8 创建了一个简单的 Flask 1.1.1 应用程序。

我正在尝试使用PdfKit实现 PDF 文件的生成,但我在引导程序渲染方面遇到了一些问题。

我已经尝试在谷歌上搜索,我发现了两篇文章:

正如 repo README.md 中所说,我已经安装了 wkhtmltopdf 的静态二进制文件:

警告!debian/ubuntu repos 中的版本减少了功能(因为它在没有 wkhtmltopdf QT 补丁的情况下编译),例如添加大纲、页眉、页脚、TOC 等。要使用此选项,您应该从 wkhtmltopdf 站点安装静态二进制文件,或者您可以使用此脚本.

有一个选项被称为--user-style-sheet用作某事的解决方法:

警告 这是 wkhtmltopdf 中此错误的解决方法。您应该先尝试 --user-style-sheet 选项。

问题是我不知道是哪个错误,因为参考页面是离线的。


代码和文件夹

项目文件夹结构如下:

WebServer/
??? Rembe
?   ??? __init__.py
?   ??? static
?   ?   ??? content
?   ?   ?   ??? bootstrap.css
?   ?   ?   ??? bootstrap.min.css
?   ?   ??? fonts
?   ?   ?   ??? glyphicons-halflings-regular.eot
?   ?   ?   ??? glyphicons-halflings-regular.svg
?   ?   ?   ??? glyphicons-halflings-regular.ttf
?   ?   ?   ??? glyphicons-halflings-regular.woff
?   ?   ?   ??? glyphicons-halflings-regular.woff2
?   ?   ??? scripts
?   ?   ?   ??? bootstrap.js
?   ?   ?   ??? bootstrap.min.js
?   ??? templates
?   ?   ??? test_page.html
?   ?   ??? test_pdf_report.html
?   ??? views.py
??? runserver.py
Run Code Online (Sandbox Code Playgroud)

重现问题的代码(避免bootstrap的东西,你可以从官网下载,我有代码):

初始化.py

WebServer/
??? Rembe
?   ??? __init__.py
?   ??? static
?   ?   ??? content
?   ?   ?   ??? bootstrap.css
?   ?   ?   ??? bootstrap.min.css
?   ?   ??? fonts
?   ?   ?   ??? glyphicons-halflings-regular.eot
?   ?   ?   ??? glyphicons-halflings-regular.svg
?   ?   ?   ??? glyphicons-halflings-regular.ttf
?   ?   ?   ??? glyphicons-halflings-regular.woff
?   ?   ?   ??? glyphicons-halflings-regular.woff2
?   ?   ??? scripts
?   ?   ?   ??? bootstrap.js
?   ?   ?   ??? bootstrap.min.js
?   ??? templates
?   ?   ??? test_page.html
?   ?   ??? test_pdf_report.html
?   ??? views.py
??? runserver.py
Run Code Online (Sandbox Code Playgroud)

运行服务器.py

from flask import Flask

app = Flask(__name__)

db = SQLAlchemy(app)

import Rembe.views
Run Code Online (Sandbox Code Playgroud)

视图.py

from os import environ, path, walk
from Rembe import app

if __name__ == '__main__':
    # Folder to monitor and check if the server needs to be reloaded
    extra_dirs = ['/home/pi/WebServer/', '/home/pi/WebServer/Rembe/', '/home/pi/WebServer/Rembe/templates/']
    extra_files = extra_dirs[:]
    for extra_dir in extra_dirs:
        for dirname, dirs, files in walk(extra_dir):
            for filename in files:
                filename = path.join(dirname, filename)
                if path.isfile(filename):
                    extra_files.append(filename)

    app.run('0.0.0.0', 80, False, extra_files=extra_files)
Run Code Online (Sandbox Code Playgroud)

test_page.html

from flask import render_template, url_for, send_from_directory
from Rembe import app
import pdfkit

@app.route('/')
@app.route('/test_page')
def test_page():
    return render_template(
        'test_page.html', title='test'
    )

@app.route('/test_view', methods=['GET', 'POST'])
def test_view():
    return render_template('test_pdf_report.html', my_custom_value='TEST PARAMETER')

@app.route('/test_download', methods=['GET', 'POST'])
def test_download():
    filename = 'report.pdf'

    string_page = render_template('test_pdf_report.html', my_custom_value='TEST PARAMETER')
    options = {'enable-local-file-access': ""}
    pdfkit.from_string(string_page, f'/tmp/{filename}')

    return send_from_directory(directory='/tmp/', filename=filename)
Run Code Online (Sandbox Code Playgroud)

test_pdf_report.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }} - TEST</title>
    <link rel="stylesheet" type="text/css" href="/static/content/bootstrap.min.css" />
</head>

<body>

    <div class="container body-content">
        <a href="{{url_for('test_view')}}">test</a>
        <label> | </label>
        <a href="{{url_for('test_download')}}">Download</a>
    </div>

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

问题

该项目生成一个带有两个可点击文本的白页:测试下载

可点击文本

单击文本测试呈现的页面是否正确并且引导程序正常工作,行/列位于正确的位置。

测试图像

单击文本Download the pdf open but bootstrap 未呈现并且行/列与页面左侧对齐。

下载图片

服务器的输出告诉我一切都很好:

Loading pages (1/6)
Counting pages (2/6)                                               
Resolving links (4/6)                                                       
Loading headers and footers (5/6)                                           
Printing pages (6/6)
Done
Run Code Online (Sandbox Code Playgroud)

我还尝试直接使用wkhtmltopdf库生成 PDF ,如下所示:

wkhtmltopdf --enable-local-file-access test_pdf_report.html /tmp/mypdf.pdf
Run Code Online (Sandbox Code Playgroud)

该命令在不渲染引导程序的情况下执行并生成 PDF,控制台输出为:

Loading pages (1/6)
Counting pages (2/6)                                               
Resolving links (4/6)                                                       
Loading headers and footers (5/6)                                           
Printing pages (6/6)
Done
Run Code Online (Sandbox Code Playgroud)

问题

我有两个问题:

  • PdfKit 模块是否与引导程序兼容?

  • 有没有办法解决我的问题并下载呈现为 HTML 页面且行/列格式正确的 PDF 文件?

感谢您的时间。

Nex*_*xeh 1

我今天遇到了同样的问题。此外,我观察到它确实加载并使用了一些引导程序。和你一样,我的所有专栏都是全宽渲染的。我相信我发现问题实际上是在 wkhtmltopdf 中。媒体查询似乎有问题。这并不能解决他们的问题,但它解释了正在发生的事情。有些人已经找到了适合他们特定情况的解决方法,但我目前还没有找到适合我的方法。

使用 wkhtmltopdf 将 Twitter bootstrap 页面转换为 PDF:span 问题

https://github.com/barryvdh/laravel-snappy/issues/258

更新

我能够降级到 Bootstrap 3 并更新我的标记以适应类名称的变化,并获得更好的结果。我相信问题是 Bootstrap 4 中添加的 Flexbox 在 wkhtmltopdf 中不起作用