Generate PDF from Plone content types

后端 未结 4 566
难免孤独
难免孤独 2021-01-06 15:09

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

相关标签:
4条回答
  • 2021-01-06 15:35

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

    0 讨论(0)
  • 2021-01-06 15:41

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

    0 讨论(0)
  • 2021-01-06 15:48

    It seems that you are searching for these:

    • Reportlab (official site) for a custom solution
    • collective.sendaspdf for an ootb solution
    0 讨论(0)
  • 2021-01-06 15:55

    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')
    
    0 讨论(0)
提交回复
热议问题