Django HTML & CSS 渲染为 pdf

Posted

技术标签:

【中文标题】Django HTML & CSS 渲染为 pdf【英文标题】:Django HTML & CSS render to pdf 【发布时间】:2020-04-12 13:33:46 【问题描述】:

我正在尝试使用 Django-weasyprint 将 html 和 CSS 转换为 pdf 页面,但我有点坚持他们的教程,因为我希望 PDF 在用户单击下载按钮时呈现当前页面并且 pdf 会以只读权限自动下载。整个过程感觉很痛苦。

目前weasyprint只是将Django中的一个URL转成pdf,但是不知道怎么设置按钮查看weasyprint视图。

也许我正在回顾它并且过于复杂化,任何帮助将不胜感激。

Weasyprints 示例代码:

from django.conf import settings
from django.views.generic import DetailView

from django_weasyprint import WeasyTemplateResponseMixin
from django_weasyprint.views import CONTENT_TYPE_PNG


class MyModelView(DetailView):
    # vanilla Django DetailView
    model = MyModel
    template_name = 'mymodel.html'


class MyModelPrintView(WeasyTemplateResponseMixin, MyModelView):
    # output of MyModelView rendered as PDF with hardcoded CSS
    pdf_stylesheets = [
        settings.STATIC_ROOT + 'css/app.css',
    ]
    # show pdf in-line (default: True, show download dialog)
    pdf_attachment = False
    # suggested filename (is required for attachment!)
    pdf_filename = 'foo.pdf'


class MyModelImageView(WeasyTemplateResponseMixin, MyModelView):
    # generate a PNG image instead
    content_type = CONTENT_TYPE_PNG

    # dynamically generate filename
    def get_pdf_filename(self):
        return 'bar-at.pdf'.format(
            at=timezone.now().strftime('%Y%m%d-%H%M'),
        )

我在我的电脑上创建了一个虚拟环境,它的设置与示例完全相同。目前使用的是 Boostrap 4。

*编辑如果有更好的方法,非常欢迎你分享:)

我还想只针对正文标签,以便它只将该部分转换为 pdf 而不是整个页面。

在此之前我使用的解决方案是:https://codepen.io/AshikNesin/pen/KzgeYX,但这不是很好。

*编辑 2.0

我已经转向 js 并且我被这个脚本困住了,它不想在 click 函数上创建 pdf 表单 还有一种方法可以将 js 函数设置为仅下载选定的 Id 在div 而不是一定规模? (怕是要用分辨率而不是实际需要渲染的内容)

https://jsfiddle.net/u4ko9pzs/18/

任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

您不需要使用该 django 应用程序。您可以按照博客文章https://www.bedjango.com/blog/how-generate-pdf-django-weasyprint/中的示例编写自定义视图来处理打印

我发现该应用程序存在限制并编写了我自己的观点。没那么难。

【讨论】:

为什么说它的限制?你想达到什么目标? weasyprint 给出了 cario 依赖错误:/ 如果你安装了 cario,它仍然不起作用 weasyprint instalation instruction 肯定有更简单的方法来呈现 pdf :) @Robert 对于我来说,Linux 和 Mac 的终端都是 2 行。至于Windows,我不知道,但我敢肯定这不是微不足道的 @somecallitblues 我在使用 GTK 时遇到的问题不记得详细了,但是因为 shure 不是 Windows 上安装的第一个选项。 MSYS2 版本不起作用(某些 Windows 服务已运行,安装过程中安装不会更改此行为)。但他们发布了maintened version,这很有效。【参考方案2】:

我试过 django-wkhtmltopdf 和 weasyprint。对于舒尔 weasyprint 允许更多的 css 主题,但它仍然不是一对一的浏览器版本。我对结果不满意。 对于表格和所有类似 word/excel 的数据都可以。但在我的情况下,我必须制作 px 到 px 的“证书”,比如带有 svg 形状背景的 pdf 然后一些缺乏功能开始成为不方便的问题。

因此,如果您需要使用相同的 css 并进行最少的修改以像在浏览器中一样获得效果,那么 puppeter 可以解决所有兼容性问题。但是这股力量要使用 Node 来运行 puppeteer。 (就我而言,我已经用它来编译资产)

Cli for puppetere:

npm i- puppeteer-pdf

then install wrapper

pip install django-puppeteer-pdf

在设置中添加节点 puppeteer cli 启动命令:

PUPPETEER_PDF_CMD = 'npx puppeteer-pdf'

并创建视图

from puppeteer_pdf import render_pdf_from_template
from django.http import HttpResponse, 
import os

# Rendering code 
context = 
    'data': 'test data'


output_temp_file = os.path.join(settings.BASE_DIR, 'static', 'temp.pdf')

pdf = render_pdf_from_template(
    input_template='path to template in templates dir'
    header_template='',
    footer_template='',
    context=context,
    cmd_options=
        'format': 'A4',
        'scale': '1',
        'marginTop': '0',
        'marginLeft': '0',
        'marginRight': '0',
        'marginBottom': '0',
        'printBackground': True,
        'preferCSSPageSize': True,
        'output': output_temp_file,
        'pageRanges': 1
    
)
#you can remove temp file now or collecte them and run some crone task.(performance)
if os.path.exists(output_temp_file):
    os.remove(output_temp_file)
else:
    # raise error or something

filename = f'filename='your donwload file name'.pdf'

response = HttpResponse(pdf, content_type='application/pdf;')
response['Content-Disposition'] = filename

要保持原始颜色,您必须添加

html
  -webkit-print-color-adjust: exact;

当您选择“preferCSSPageSize”时控制页面大小和边距。

@page 
  size: A4;
  margin: 0 0 0 0;

【讨论】:

【参考方案3】:

使用whkhtmltopdf,它在 Django 中非常容易使用。它提供纯 html 生成的 PDF 转换

pip install django-wkhtmltopdf

https://django-wkhtmltopdf.readthedocs.io/en/latest/

【讨论】:

以上是关于Django HTML & CSS 渲染为 pdf的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Django 模板中重现 CSS 效果

Django 使用清晰的表单用 css 渲染表单字段

Django:使用静态、困难的时间和路径来渲染 css

带有 Tailwind CSS 的 Django-Tinymce

Django 模板迭代和渲染函数返回的列表中的项目

django 模板关闭特殊字符转化