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
use z3c.rml, works very well to produce pdf from an rml template, instead of converting from html which can be tricky.
Produce and Publish Lite is self-contained, open-source code and the successor to SmartPrintNG. http://pypi.python.org/pypi/zopyx.smartprintng.lite/
It seems that you are searching for these:
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:
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')