在Django站点中将HTML呈现为PDF

111 html python pdf django pdf-generation

对于我的django支持的网站,我正在寻找一个简单的解决方案,将动态html页面转换为pdf.

页面包括来自Google可视化API的HTML和图表(基于javascript,但包括这些图表是必须的).

Gui*_*ert 202

尝试使用Reportlab的解决方案.

下载并使用python setup.py install照常安装

您还需要安装以下模块:xhtml2pdf,html5lib,带有easy_install的pypdf.

这是一个用法示例:

首先定义这个函数:

import cStringIO as StringIO
from xhtml2pdf import pisa
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
from cgi import escape


def render_to_pdf(template_src, context_dict):
    template = get_template(template_src)
    context = Context(context_dict)
    html  = template.render(context)
    result = StringIO.StringIO()

    pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("ISO-8859-1")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

def myview(request):
    #Retrieve data or whatever you need
    return render_to_pdf(
            'mytemplate.html',
            {
                'pagesize':'A4',
                'mylist': results,
            }
        )
Run Code Online (Sandbox Code Playgroud)

模板:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>My Title</title>
        <style type="text/css">
            @page {
                size: {{ pagesize }};
                margin: 1cm;
                @frame footer {
                    -pdf-frame-content: footerContent;
                    bottom: 0cm;
                    margin-left: 9cm;
                    margin-right: 9cm;
                    height: 1cm;
                }
            }
        </style>
    </head>
    <body>
        <div>
            {% for item in mylist %}
                RENDER MY CONTENT
            {% endfor %}
        </div>
        <div id="footerContent">
            {%block page_foot%}
                Page <pdf:pagenumber>
            {%endblock%}
        </div>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.

  • 在python3中,除了将`cStringIO.StringIO`转换为`io.StringIO`之外,我们必须将`result`定义为`result = io.BytesIO()`而不是`result = StringIO`. (11认同)
  • +1我已经使用这个解决方案一年了,它很棒.PISA甚至可以创建带有简单标签的条形码,还有更多.而它*易*. (9认同)
  • 似乎没有运行Javascript. (5认同)
  • pisa现在分发为xhtml2pdf (3认同)

laf*_*ste 11

https://github.com/nigma/django-easy-pdf

模板:

{% extends "easy_pdf/base.html" %}

{% block content %}
    <div id="content">
        <h1>Hi there!</h1>
    </div>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

视图:

from easy_pdf.views import PDFTemplateView

class HelloPDFView(PDFTemplateView):
    template_name = "hello.html"
Run Code Online (Sandbox Code Playgroud)

如果你想在Python 3上使用django-easy-pdf,请查看此处建议的解决方案.

  • 这是迄今为止我尝试过的选项中最容易实现的选项。对于我的需要(从 html 版本生成 pdf 报告)这只是简单的工作。谢谢! (2认同)

小智 10

我刚刚为CBV鞭打了这个.不在生产中使用,但为我生成PDF.可能需要为事情的错误报告方面工作,但到目前为止做的伎俩.

import StringIO
from cgi import escape
from xhtml2pdf import pisa
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.views.generic import TemplateView

class PDFTemplateResponse(TemplateResponse):

    def generate_pdf(self, retval):

        html = self.content

        result = StringIO.StringIO()
        rendering = pisa.pisaDocument(StringIO.StringIO(html.encode("ISO-8859-1")), result)

        if rendering.err:
            return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
        else:
            self.content = result.getvalue()

    def __init__(self, *args, **kwargs):
        super(PDFTemplateResponse, self).__init__(*args, mimetype='application/pdf', **kwargs)
        self.add_post_render_callback(self.generate_pdf)


class PDFTemplateView(TemplateView):
    response_class = PDFTemplateResponse
Run Code Online (Sandbox Code Playgroud)

使用如下:

class MyPdfView(PDFTemplateView):
    template_name = 'things/pdf.html'
Run Code Online (Sandbox Code Playgroud)


jit*_*hin 10

尝试wkhtmltopdf 与下列任何一个包装器

django-wkhtmltopdfpython-pdfkit

这对我很有用,支持javascript和css或webkit浏览器支持的任何内容.

有关更详细的教程,请参阅此博客文章


nas*_*sim 6

我在这个线程中尝试了最佳答案,但它不适用于 python3.8,因此我必须进行一些更改,如下所示(对于任何使用 python3.8 的人):

import io 
from xhtml2pdf import pisa
from django.http import HttpResponse
from html import escape

from django.template.loader import render_to_string

def render_to_pdf(template_src, context_dict):
    html = render_to_string(template_src, context_dict)
    result = io.BytesIO()



    pdf = pisa.pisaDocument(io.BytesIO (html.encode("utf-8")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
Run Code Online (Sandbox Code Playgroud)

我必须更改cgi为,html因为cgi.escape已被废弃,并且我StringIOio.ByteIO()as 替换了我使用的渲染,render_to_string而不是转换dictcontext引发错误的。