[IMP] report_webkit: some improvements, notably the use of "makoed" jinja like email_template

and shortcut to extend evaluation context

bzr revid: nicolas.vanhoren@openerp.com-20130226153524-ny52u94g2l4qtcwk
This commit is contained in:
niv-openerp 2013-02-26 16:35:24 +01:00
commit 108d5f1d6c
6 changed files with 118 additions and 47 deletions

View File

@ -36,5 +36,6 @@ import webkit_report
import ir_report
import wizard
import convert
import report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -55,7 +55,7 @@
<body style="border:0; margin: 0;" onload="subst()">
<table class="header" style="border-bottom: 0px solid black; width: 100%">
<tr>
<td>${helper.embed_company_logo()|n}</td>
<td>${helper.embed_company_logo()|safe}</td>
<td style="text-align:right"> </td>
</tr>
<tr>
@ -63,21 +63,21 @@
<td style="text-align:right"> </td>
</tr>
<tr>
<td>${company.partner_id.name |entity}</td>
<td>${company.partner_id.name}</td>
<td/>
</tr>
<tr>
<td >${company.partner_id.street or ''|entity}</td>
<td >${company.partner_id.street or ''}</td>
<td/>
</tr>
<tr>
<td>Phone: ${company.partner_id.phone or ''|entity} </td>
<td>Phone: ${company.partner_id.phone or ''} </td>
<td/>
</tr>
<tr>
<td>Mail: ${company.partner_id.email or ''|entity}<br/></td>
<td>Mail: ${company.partner_id.email or ''}<br/></td>
</tr>
</table> ${_debug or ''|n} </body>
</table> ${_debug or ''|safe} </body>
</html>]]>
</field>
<field eval="55.0" name="margin_top"/>

View File

@ -0,0 +1,2 @@
import webkit_report_demo

View File

@ -11,6 +11,7 @@
% endfor
</ul>
<p>The administrator name is: ${admin_name}</p>
<p>If this report does not contain headers, it is because you have a badly compiled wkhtmltopdf. Consider installing
the static version distributed on the official web site: <a href="https://code.google.com/p/wkhtmltopdf/">https://code.google.com/p/wkhtmltopdf/</a>.</p>
</body>

View File

@ -0,0 +1,11 @@
from openerp.addons.report_webkit.webkit_report import webkit_report_extender
from openerp import SUPERUSER_ID
@webkit_report_extender("report_webkit.webkit_demo_report")
def extend_demo(pool, cr, uid, localcontext, context):
admin = pool.get("res.users").browse(cr, uid, SUPERUSER_ID, context)
localcontext.update({
"admin_name": admin.name,
})

View File

@ -38,10 +38,6 @@ import tempfile
import time
import logging
from mako.template import Template
from mako.lookup import TemplateLookup
from mako import exceptions
from openerp import netsvc
from openerp import pooler
from report_helper import WebKitHelper
@ -50,16 +46,72 @@ from openerp import addons
from openerp import tools
from openerp.tools.translate import _
from openerp.osv.osv import except_osv
from urllib import urlencode, quote as quote
_logger = logging.getLogger(__name__)
try:
# We use a jinja2 sandboxed environment to render mako templates.
# Note that the rendering does not cover all the mako syntax, in particular
# arbitrary Python statements are not accepted, and not all expressions are
# allowed: only "public" attributes (not starting with '_') of objects may
# be accessed.
# This is done on purpose: it prevents incidental or malicious execution of
# Python code that may break the security of the server.
from jinja2.sandbox import SandboxedEnvironment
mako_template_env = SandboxedEnvironment(
block_start_string="<%",
block_end_string="%>",
variable_start_string="${",
variable_end_string="}",
comment_start_string="<%doc>",
comment_end_string="</%doc>",
line_statement_prefix="%",
line_comment_prefix="##",
trim_blocks=True, # do not output newline after blocks
autoescape=True, # XML/HTML automatic escaping
)
mako_template_env.globals.update({
'str': str,
'quote': quote,
'urlencode': urlencode,
})
except ImportError:
_logger.warning("jinja2 not available, templating features will not work!")
def mako_template(text):
"""Build a Mako template.
This template uses UTF-8 encoding
"""
tmp_lookup = TemplateLookup() #we need it in order to allow inclusion and inheritance
return Template(text, input_encoding='utf-8', output_encoding='utf-8', lookup=tmp_lookup)
return mako_template_env.from_string(text)
_extender_functions = {}
def webkit_report_extender(report_name):
"""
A decorator to define functions to extend the context used in a template rendering.
report_name must be the xml id of the desired report (it is mandatory to indicate the
module in that xml id).
The given function will be called at the creation of the report. The following arguments
will be passed to it (in this order):
- pool The model pool.
- cr The cursor.
- uid The user id.
- localcontext The context given to the template engine to render the templates for the
current report. This is the context that should be modified.
- context The OpenERP context.
"""
def fct1(fct):
lst = _extender_functions.get(report_name)
if not lst:
lst = []
_extender_functions[report_name] = lst
lst.append(fct)
return fct
return fct1
class WebKitParser(report_sxw):
"""Custom class that use webkit to render HTML reports
@ -201,6 +253,17 @@ class WebKitParser(report_sxw):
def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):
"""generate the PDF"""
# just try to find an xml id for the report
cr = cursor
import openerp.pooler as pooler
pool = pooler.get_pool(cr.dbname)
found_xml_ids = pool.get("ir.model.data").search(cr, uid, [["model", "=", "ir.actions.report.xml"], \
["res_id", "=", report_xml.id]], context=context)
xml_id = None
if found_xml_ids:
xml_id = pool.get("ir.model.data").read(cr, uid, found_xml_ids[0], ["module", "name"])
xml_id = "%s.%s" % (xml_id["module"], xml_id["name"])
if context is None:
context={}
htmls = []
@ -242,64 +305,57 @@ class WebKitParser(report_sxw):
if not css :
css = ''
#default_filters=['unicode', 'entity'] can be used to set global filter
body_mako_tpl = mako_template(template)
helper = WebKitHelper(cursor, uid, report_xml.id, context)
self.parser_instance.localcontext['helper'] = helper
self.parser_instance.localcontext['css'] = css
self.parser_instance.localcontext['_'] = self.translate_call
# apply extender functions
additional = {}
if xml_id in _extender_functions:
for fct in _extender_functions[xml_id]:
fct(pool, cr, uid, self.parser_instance.localcontext, context)
if report_xml.precise_mode:
for obj in objs:
self.parser_instance.localcontext['objects'] = [obj]
ctx = dict(self.parser_instance.localcontext)
for obj in self.parser_instance.localcontext['objects']:
ctx['objects'] = [obj]
try :
html = body_mako_tpl.render(helper=helper,
css=css,
_=self.translate_call,
**self.parser_instance.localcontext)
html = body_mako_tpl.render(dict(ctx))
htmls.append(html)
except Exception:
msg = exceptions.text_error_template().render()
except Exception, e:
msg = u"%s" % e
_logger.error(msg)
raise except_osv(_('Webkit render!'), msg)
else:
try :
html = body_mako_tpl.render(helper=helper,
css=css,
_=self.translate_call,
**self.parser_instance.localcontext)
html = body_mako_tpl.render(dict(self.parser_instance.localcontext))
htmls.append(html)
except Exception:
msg = exceptions.text_error_template().render()
msg = u"%s" % e
_logger.error(msg)
raise except_osv(_('Webkit render!'), msg)
head_mako_tpl = mako_template(header)
try :
head = head_mako_tpl.render(helper=helper,
css=css,
_=self.translate_call,
_debug=False,
**self.parser_instance.localcontext)
except Exception:
raise except_osv(_('Webkit render!'),
exceptions.text_error_template().render())
head = head_mako_tpl.render(dict(self.parser_instance.localcontext, _debug=False))
except Exception, e:
raise except_osv(_('Webkit render!'), u"%s" % e)
foot = False
if footer :
foot_mako_tpl = mako_template(footer)
try :
foot = foot_mako_tpl.render(helper=helper,
css=css,
_=self.translate_call,
**self.parser_instance.localcontext)
except:
msg = exceptions.text_error_template().render()
foot = foot_mako_tpl.render(dict({},
**self.parser_instance.localcontext))
except Exception, e:
msg = u"%s" % e
_logger.error(msg)
raise except_osv(_('Webkit render!'), msg)
if report_xml.webkit_debug :
try :
deb = head_mako_tpl.render(helper=helper,
css=css,
_debug=tools.ustr("\n".join(htmls)),
_=self.translate_call,
**self.parser_instance.localcontext)
except Exception:
msg = exceptions.text_error_template().render()
deb = head_mako_tpl.render(dict(self.parser_instance.localcontext, _debug=tools.ustr("\n".join(htmls))))
except Exception, e:
msg = u"%s" % e
_logger.error(msg)
raise except_osv(_('Webkit render!'), msg)
return (deb, 'html')