如何从 Flask 中的 jinja 模板创建 PDF 文件? [问题标记为 pythonanywhere]

How can I create a PDF file from jinja template in Flask? [question tagged pythonanywhere]

我的网络应用程序是用 Flask 编写的。我想将 jinja 模板(HTML 格式)转换为 PDF 文件。我使用 pythonanywhere.com 作为我的应用程序的主机。

我已经使用 pdfkit、wkhtmltopdf、jinja2 运行ning 在开发环境 fedora31 上使用 Flask 成功生成了动态 PDF。尝试在 pythonanywhere 环境中安装 pdfkit 时,我收到消息权限被拒绝。

对于weasyprint,还需要安装库;这也是 pythonanywhere.com.

的限制

同样的情况是xhtml2pdf无法安装在pythonanywhere.com

总而言之:pdfkit、weasyprint、xhtml2pdf 目前不是可行的替代方案,而需要在 pythonanywhere.com

安装库

在 pythonanywhere.com 中存在此限制以安装新库。

我的问题是:

我有什么可行的替代方法可以将 jinja 模板转换为 PDF 格式知道我的 Flask 应用程序需要 pythonanywhere.com 到 运行 提供的环境?

任何解决这种情况的指导将不胜感激。谢谢。

在 pythonanywhere bash 控制台中发送的消息明确指出:“考虑使用‘--user’选项或检查权限”

所以安装 pdfkit 库的命令是:

pip3 安装 --user pdfkit

因此,要在 pythonanywhere 环境中安装 wkhtmltopdf 库,命令类似于:

pip3 安装 --user wkhtmltopdf

作为一个有趣的点,我在网站上发现 https://pypi.org/project/Flask-WkHTMLtoPDF/ Flask-WkHTMLtoPDF 0.1.0 库将 JavaScript 依赖的 Flask 模板转换为 PDF。

使用命令 pip3 install 安装 pdfkitwkhtmltopdfWkHTMLtoPDF 库后--用户命令。

这些库位于 /home/todonatacion/.local/lib/python3.7/site-packages 目录中。在Flask中执行应用程序,得到如下错误信息:2020-07-08 07:17:54,963: ModuleNotFoundError: No module named 'pdfkit' 2020-07 -08 07:17:54,964:文件“/var/www/todonatacion_pythonanywhere_com_wsgi.py”,第 16 行,在

库安装在我网站的本地目录/home/todonatacion/.local/lib/python3.7/site-packages

python中的指令:importpdfkit找不到库在哪里。显然,有必要在应用程序的导入语句中包含正确的路径名才能找到库。

由于import pdfkit语句找不到库的位置,问题是:如何告诉应用程序在哪里可以找到pdfkit库? 任何帮助将不胜感激。谢谢。

我的 Flask 应用程序在 pythonanywhere.com 中使用的版本是 Python 3.8,如以下屏幕截图所示:

我登录到 pythonanywhere.com 提供的 bash 控制台,仔细检查分配给我帐户的环境中可用的 python 版本。当以下命令 运行 调用 python 解释器时,我执行的检查是检查 python 的确切版本:python3.8,python3.7,python3.6、python3.5 和 python2.7

我发现输入python3.8命令时python解释器的版本是3.8.0

当输入python3.7命令时python解释器的版本是3.7.5

对于python3.6命令,版本是3.6.9;对于 python3.5,版本是 3.5.9,对于 python2.7 命令,版本是 2.7.12

这个分析的有趣之处让我想知道。 如果我用 python3 命令调用 python 解释器会发生什么?

运行 python3 来自 python 任何地方 bash 控制台的命令 确认python 解释器的版本是 3.7.5

这确认如果我想要调用python 3.8 版 的解释器,我应该 执行命令python3.8

pdfkit 库安装在 pythonanywhere 环境中时。它是从分配给我帐户的 bash 控制台完成的。安装是使用命令 pip3 install --user pdfkit

执行命令pip3 install --user pdfkit时验证库安装成功

由于python3调用了python3.7.5版本的解释器,我们可以推导出在使用pip3命令安装pdfkit库时,库安装在python 3.7.5 版 python 任何地方!!!可以通过随附的屏幕截图进行确认:

根据此信息可以确定 Flask 应用程序 运行ning 在 python 提供的 python v3.8 (3.8.0) 解释器环境中 pythonanywhere 和pdfkit 库安装在 pythonanywhere 提供的 python3.7 环境 (3.7.5) - 当然这可能会导致 [=525 之间可能出现问题=]ning pdfkit 库(运行ning 版本 3.7.5)和 Flask 中的应用程序(运行ning 版本 3.8.0)

pdfkit 库已在路径 /home/todonatacion/.local/lib/python3.7/site-packages[ 中为用户帐户本地安装=46=]

为了减轻报告的错误 ModuleNotFoundError: No module named 'pdfkit' 我们需要告诉 app.py 在 Flask 哪里可以找到 pdfkit 库。

另一种可行的方法是在 app.py 中包含以下代码:

此代码询问库是否在路径名中,如果不在,则包含它。这样导入pdfkit就可以完成了。

为了减少在app.py 运行ning 在 python3.8 和库 运行ning 在 python3 (3.7.5) 之间的兼容性,因此使用pip3.8 命令在本地执行库安装。 #SEE A must-read 用于在 pythonanywhere.com 安装 python 模块(例如库/包) 在以下 link:

https://help.pythonanywhere.com/pages/InstallingNewModules

Pythonanywhere.com 状态:

  1. 在 Python任何地方使用 --user 标志安装 Python 模块

“您可以使用 Bash 控制台在 Python 任何地方安装新模块。” 示例:要为 Python 3.6 安装 pwhich 模块,您需要 运行 在 Bash 控制台(而不是 Python一):

示例:

pip3.6 安装 --user pwhich

  1. 在Python任何地方使用virtualenv
  2. 安装Python模块

"如果你创建一个 virtualenv,你可以安装你想要的各种包的任何版本。但是,在 virtualenv 中,不需要上面提到的 --user。 进入 virtualenv 后,要安装软件包,您只需使用不带 Python 版本号或 --user 标志的 pip:"

示例:

(my-virtualenv) $pip install pwhich

因此,在使用命令 pip3.8 install --user pdfkit

执行 pdfkit 库的安装时

在任何地方使用 python bash 控制台,您将获得:

现在我们在python3.8环境

的本地路径下安装了pdfkit库

为确保app.py可以与安装在python3.8环境中的pdfkit库一起工作,我们更新了app.py源代码中的路径名,使路径名pdfkit库是根据python3.8

的版本添加的

因此,要在 pythonanywhere 环境中安装 wkhtmltopdf 库,命令类似于:

pip3.8 安装 --user wkhtmltopdf

此调用的问题是 我如何在 Flask 中从 jinja 模板创建 PDF 文件? 那么,一旦安装了 pdfkitwkhtmltopdf 库已经解决,我在 Flask 运行s 中的应用程序在 Pythonanywhere。具体来说,我得到了主屏幕。当我使 selection 打印报告时。具体调用路由 @app.route('/ print_report001') 我收到错误消息:

OSError:wkhtmltopdf 已退出,代码为 non-zero -6。错误: QxcbConnection:无法连接到显示器 ** 不匹配

# pdfkit implementation
@app.route('/print_report001')
def print_report001():


    now = datetime.now()
    current_report_date = now.strftime("%Y-%m-%d %H:%M:%S")

    rendered = render_template(
        'report_001.html', 
        report_title = "Report 001", 
        current_report_date = current_report_date
    )

    pdf = pdfkit.from_string(rendered, False)
    response = make_response(pdf)
    response.headers['Content-Type']='application/pdf'
    response.headers['Content-Disposition']='inline; filename=report_001.pdf'
    return response

相同的代码在我的本地开发站 fedora31 和 python3.8 以及 pdfkit 和 wkhtmltopdf 库上完美运行。出于某种原因,@app.route('/print_report001') 在 pythonanywhere.com 服务器上 运行 时不起作用。有什么我没有考虑过的遗漏吗?解决此错误的任何方向将不胜感激。谢谢。

通过在 pythonanywhere.com 搜索 Flask 应用 运行time 环境,发现 Flask 应用 运行s 在 "Ubuntu”版本“16.04.6 LTS(Xenial Xerus)”

正在调查 ***QxcbConnection 错误:无法连接到显示器 ** 不匹配 ***** 技术文档表明该错误可能与 xvfb 有关,这导致了问题: 如何在由 pythonanywhere.com 托管的 Ubuntu 版本 16.04.6 LTS (Xenial Xerus) 中安装 xvfb?

根据 Ubuntu 文档“Xvfb 是一个 X 服务器,可以 运行 在没有显示硬件和物理输入设备的机器上。它模拟使用虚拟内存的哑帧缓冲区。” (#SEE Source: http://manpages.ubuntu.com/manpages/xenial/man1/Xvfb.1.html and select tab 16.04 LTS) 建议安装 xvfb 模块是必需的。

安装 xvfb

“在 Ubuntu 16.04 (Xenial Xerus) 上安装 xvfb 包就像 运行 在终端上执行以下命令一样简单:”(#SEE:https://howtoinstall.co/en/ubuntu/xenial/xvfb)

sudo apt-get更新

sudo apt-get 安装 xvfb

在 pythonanywhere.com 的帐户中没有超级用户权限来执行这些命令让我们回到了问题 How to install xvfb in Ubuntu pythonanywhere.com?

托管的版本 16.04.6 LTS (Xenial Xerus)

如果能提供解决这种情况的指南,我们将不胜感激。谢谢!

Pythonanywhere.com 创建了一个新的虚拟系统。我们继续在新的虚拟系统上测试 app.py。并观察是否仍然存在相同的错误。

我已经在任何地方查看了文件“python。com/user/todonatacion/files/var/log/…&q哦;并再次生成相同的错误。 “OSError:wkhtmltopdf 以 non-zero 代码 -6 退出。错误:QXcbConnection:无法连接以显示不匹配”

错误消息明确指出 *"OSError: wkhtmltopdf exited with non-zero code -6。错误: QXcbConnection:无法连接到显示器 ** 不匹配 ***

当执行命令时:dpkg -s wkhtmltopdf 来自 pythonanywhere bash 控制台从 wkhthmltopdf 库获取信息,包括:包名称 (wkhtmltpdf)、包安装状态、依赖项以及使用包的建议。

寻找解决方案的重点是确定是否安装了wkhtmltopdf包的所有DEPENDENCIES和RECOMMENDATIONS.

运行 命令 wkhtmltopdf 报告 001.html 从 pythonanywhere bash 控制台命令报告 001.pdf行获取消息:QXcbConnection:无法连接到显示 中止

出于演示目的,通过在本地开发系统 fedora31

$ wkhtmltopdf report_001.html report_001.pdf

正在加载页面 (1/2)

正在打印页面 (2/2)

完成

$

成功获取pdf格式的报告_001.pdf

鉴于结果不如预期。下一步是确认推荐的依赖到运行wkhtmltopdf是否安装 pythonanywhere.com - 需要的推荐依赖项是 xserverxvfb。为此,我们将使用 dpkg -s xserver 命令和 dpkg xvfb 命令。

在python任何地方bash控制台执行dpkg -s xserver命令确认没有安装xserver包并且没有关于xserver的信息。

运行 命令 dpkg -s xvfb 在 pythonanywhere bash 控制台确认 xvfb 软件包 已安装.

由于 pythonanywhere 服务器没有附加显示器,Pythonanywhere 支持建议使用“PyVirtualDisplay”库。 *

"The servers where your code runs on PythonAnywhere don't have attached displays, so there's no X server. Instead, you need to use a virtual display. Try adding from pyvirtualdisplay import Display to the top of your script, and then wrapping the code that calls wkhtmltopdf in a with Display(): and see if that helps"

包装使用“wkhtmltopdf”的代码的实现如下:

import pdfkit # needed to convert jinja templates to PDF file

from pyvirtualdisplay import Display # pyvirtualdisplay is a python wrapper
                                     # for Xvfb, Xephyr and Xvnc
                                     # SEE: https://pypi.org/project/PyVirtualDisplay/




@app.route('/print_report001')
def print_report001():

    now = datetime.now()
    current_report_date = now.strftime("%Y-%m-%d %H:%M:%S")

    rendered = render_template(
        'report_001.html', 
        report_title = "Report 001", 
        current_report_date = current_report_date
    )


    disp = Display().start()
    # display is active
    pdf = pdfkit.from_string(rendered, False)
    response = make_response(pdf)
    response.headers['Content-Type']='application/pdf'
    response.headers['Content-Disposition']='inline; filename=report_001.pdf'
    disp.stop()
    # display is stopped
    return response

结果是一份完美转换为 PDF 格式的报告。