从 Plone 内容类型生成 PDF

发布于 2024-12-06 11:58:36 字数 392 浏览 0 评论 0原文

我需要从内容类型创建 PDF(如果重要的话,可以灵活地制作),以便用户创建一个新文档,并在填写表单后生成 PDF 并准备下载。因此,基本上在创建/修改文档后,应该创建一个 PDF 并将其存储在 ZODB 中(实际上我使用的是 blob),以便我可以将视图与“下载为 PDF”链接。

我见过 PDFNode 但它似乎不是我要找的。还有 Produce &发布,但它是一个网络服务(?),而我要为其开发此服务的公司不想(出于隐私考虑)将数据发送到其数据中心之外。

有什么想法吗?

I need to create PDFs from content types (made with dexerity if that matters) so that the user creates a new document and after filling the form a PDF is generated and ready to be downloaded. So basically after creating/modifying the document a PDF should be created and stored in ZODB (actually I'm using blobs) so that I could link the view with a "Download as PDF".

I've seen PDFNode but it doesn't seem to be what I'm looking for. There's also Produce & Publish but it's a webservice(?) and the company I'm going to develop this for doesn't want (for privacy) to send data outside their datacenters.

Any idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

何止钟意 2024-12-13 11:58:36

您似乎正在搜索这些:

It seems that you are searching for these:

八巷 2024-12-13 11:58:36

事实上,我在我的一个项目中经常做这种事情。我使用了 Products.SmartPrintNG 和 fop,但没有按照产品使用的标准方式进行操作(我认为它使用 javascript 来启动转换..很奇怪)。

有几件事:

  • 我必须清理输出,因为 fop 非常敏感
  • ,使用 lxml
  • 我使用原型

无论如何,我用于创建 PDF 的事件处理程序最终看起来像这样:

from Products.SmartPrintNG.browser import SmartPrintView
from lxml.cssselect import CSSSelector
from lxml.html import fromstring, tostring
import re

san_re = re.compile('(?P<width>width\=("|\')\d{1,5}(px|%|in|cm|mm|em|ex|pt|pc)?("|\'))')

class Options(object):

    def __init__(self, __dict):
        self.__dict = __dict

    def __getattr__(self, attr):
        if self.__dict.has_key(attr):
            return self.__dict[attr]
        raise AttributeError(attr)

def sanitize_xml(xml):
    selector = CSSSelector('table,td,tr')
    elems = selector(xml)
    for el in elems:
        if el.attrib.has_key('width'):
            width = el.attrib['width']
            style = el.attrib.get('style', '').strip()
            if style and not style.endswith(';'):
                style += ';'
            style += 'width:%s;' % width
            del el.attrib['width'] 
            el.attrib['style'] = style

    return xml

def save_pdf(obj, event):
    smartprint = SmartPrintView(obj, obj.REQUEST)
    html = obj.restrictedTraverse('view')()
    xml = fromstring(html)
    selector = CSSSelector('div#content')
    xml = selector(xml)
    html = tostring(sanitize_xml(xml[0]))
    res = smartprint.convert(
        html=html,
        format='pdf2',
        options=Options({'stylesheet': 'pdf_output_stylesheet', 'template': 'StandardTemplate'})
    )

    field = obj.getField('generatedPDF')
    field.set(obj, res, mimetype='application/pdf', _initializing_=True)
    field.setFilename(obj, obj.getId() + '.pdf')

I actually do this sort of thing a lot on a project of mine. I used Products.SmartPrintNG and fop for it though and didn't do it the standard way that the product uses(I think it uses javascript to initiate the conversion.. weird).

Couple things:

  • I had to sanitize the output since fop is pretty touchy
  • used lxml
  • mine uses archetypes

Anyways, my event handler for creating the PDF ends up looking something like this:

from Products.SmartPrintNG.browser import SmartPrintView
from lxml.cssselect import CSSSelector
from lxml.html import fromstring, tostring
import re

san_re = re.compile('(?P<width>width\=("|\')\d{1,5}(px|%|in|cm|mm|em|ex|pt|pc)?("|\'))')

class Options(object):

    def __init__(self, __dict):
        self.__dict = __dict

    def __getattr__(self, attr):
        if self.__dict.has_key(attr):
            return self.__dict[attr]
        raise AttributeError(attr)

def sanitize_xml(xml):
    selector = CSSSelector('table,td,tr')
    elems = selector(xml)
    for el in elems:
        if el.attrib.has_key('width'):
            width = el.attrib['width']
            style = el.attrib.get('style', '').strip()
            if style and not style.endswith(';'):
                style += ';'
            style += 'width:%s;' % width
            del el.attrib['width'] 
            el.attrib['style'] = style

    return xml

def save_pdf(obj, event):
    smartprint = SmartPrintView(obj, obj.REQUEST)
    html = obj.restrictedTraverse('view')()
    xml = fromstring(html)
    selector = CSSSelector('div#content')
    xml = selector(xml)
    html = tostring(sanitize_xml(xml[0]))
    res = smartprint.convert(
        html=html,
        format='pdf2',
        options=Options({'stylesheet': 'pdf_output_stylesheet', 'template': 'StandardTemplate'})
    )

    field = obj.getField('generatedPDF')
    field.set(obj, res, mimetype='application/pdf', _initializing_=True)
    field.setFilename(obj, obj.getId() + '.pdf')
雨的味道风的声音 2024-12-13 11:58:36

Produce and Publish Lite 是独立的开源代码,是 SmartPrintNG 的后继者。 http://pypi.python.org/pypi/zopyx.smartprintng.lite/

Produce and Publish Lite is self-contained, open-source code and the successor to SmartPrintNG. http://pypi.python.org/pypi/zopyx.smartprintng.lite/

夜光 2024-12-13 11:58:36

使用 z3c.rml,可以很好地从 rml 模板生成 pdf,而不是从可能很棘手的 html 转换。

use z3c.rml, works very well to produce pdf from an rml template, instead of converting from html which can be tricky.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文