正如其他人所提到的,最好的方法是生成一个模板,然后使用周围众多库之一将结果转换为 PDF。此方法为您提供对模板的通常控制量,例如使用标签。
我使用了前面提到的 ReportLab/Pisa 设置,但发现它的局限性很大,大多数布局必须使用表格构建,并且 CSS2 规范的许多部分尚未实现。
wkhtmltopdf 是一个更易于使用的库,它是 WebKit 的无头发行版。这样做的好处是可以像任何 webkit 浏览器一样呈现您的模板,从而让您可以使用 webkit 特定的附加功能,例如 WebKit 中存在的 CSS3 规范的一部分。
使用包装库django-wkhtmltopdf,您可以在视图中使用render_to_pdf,而不是通常的Django render_to_response。
免责声明:我是这个库的贡献者。
更新
此库已转换为 CBV,为了方便起见,下面的大部分信息(我将留下以帮助添加一些上下文)现在已在库本身中实现。
有关如何实现以下代码块的示例,请参阅 quickstart 文档。如果您需要使用更高级的用法,您可以继承 PDFTemplateView 并添加各种选项,例如文件名和边距。
示例视图:
from django.shortcuts import render_to_response
from wkhtmltopdf import render_to_pdf
def pdf(request):
context.update({'objects': ModelA.objects.filter(p_id=100)})
kwargs = {}
if request.GET and request.GET.get('as', '') == 'html':
render_to = render_to_response
else:
render_to = render_to_pdf
kwargs.update(dict(
filename='model-a.pdf',
margin_top=0,
margin_right=0,
margin_bottom=0,
margin_left=0))
return render_to('pdf.html', context, **kwargs)
这里的条件语句允许您将 ?as=html 传递给视图,以便您可以在浏览器中进行开发。目前这样做有点丑陋,但我们计划很快在一个版本中解决这个问题。
使用此视图,您可以像往常一样在视图中循环 objects 的内容,甚至可以扩展您的基本模板。我通常专门为 PDF 使用不同的样式表以实现样式的可维护性和可读性,因为您需要为 PDF 做一些不同的事情,例如如果您想将页脚块保持在同一个地方,请设置最小高度.
在此说明中,您可以创建将在 PDF 的每一页上使用的页眉和页脚模板,方法是将它们作为 kwargs 的一部分传递给 render_to_pdf。