使用具有通用 header/footer 和分页的 WeasyPrint 生成 PDF

Generate PDF with WeasyPrint having common header/footer and pagination

我正在使用 Wea​​syPrint 在 Django 中生成 PDF。我可以从静态 html 文件生成 pdf,如下所示 -

from django.template import Context, Template
import weasyprint

with open('static_file.html', 'r') as myfile:
    html_str = myfile.read()

template = Template(html_message)
    context = Context({'some_key': 'some_value'})
    rendered_str = template.render(context)

weasyprint.HTML(string=rendered_str).write_pdf('generated.pdf')

但我想生成一个PDF,其中我可以在每个页面中包含一个常见的header/footer并添加分页。

此外,如果有人能告诉您如何包含自定义字体来生成 PDF,那将非常有帮助。我已经在 OS (Ubuntu 14.04) 中安装了字体,但它不起作用。

关于这些我在网上搜索了很多。但找不到合适的解决方案。

由于 Weasyprint 支持 CSS 分页媒体模块级别 3,简单 headers 和页脚(例如分页,就像你提到的)可以使用CSS:

@page {
    @top-right{
        content: "Page " counter(page) " of " counter(pages);
    }
}

确保在呈现时包含样式表:

HTML(string=rendered_html,
     base_url=settings.SITE_URL).write_pdf(stylesheets=[CSS(settings.STATIC_ROOT + '/css/pdf_render.css')])

然而,渲染得更 复杂 headers/footers 可能会更……复杂。有些人提出了在 header 中包含一个 div 元素的方法,该元素仅为打印呈现(但我必须承认我只能使用这种方法正确呈现简单的元素):

@page {
    @top-left {
        content: element(pageHeader);
    }
}
@media print {
    #divHeader{
        position: running(pageHeader);
    }
}

还有另一种使用固定位置的方法,如本要点所示:https://gist.github.com/pikhovkin/5642563

当前 运行 个元素 are not supported by WeasyPrint. Nevertheless I found a way to achieve the same result using named strings:

 @page {
   @top-center {
     content:  string(title);
   }
 }

 header {
   width: 0;
   height: 0;
   visibility: hidden;
   string-set: title content();
}

现在您可以将您的内容添加到不可见的 HTML header 元素中。

<header>Content of the header goes here</header>

我可以简单地通过使用 position: fixed 作为页眉和页脚来实现它。

首先,由于固定位置的元素在页面上不占space,因此您必须通过在页面上留出适当的边距来考虑它,例如:

@page {
    margin: 5cm 0 3cm 0;
    size: A4;
}

然后根据此页边距简单地定位页眉和页脚:

header, footer {
    position: fixed;
    left: 0;
    right: 0;
}
header {
    /* subtract @page margin */
    top: 5cm;
    height: 5cm
}
footer {
    /* subtract @page margin */
    bottom: 3cm;
    height: 3cm;
}

有了这个,你可以在 <header><footer> 元素中放置任意 HTML,它们将在每一页上重复。

页面计数器似乎在那里不起作用,因此您需要根据其他答案中所述的 @page 规则实施它们。