summaryrefslogtreecommitdiff
path: root/addons/mail/models/mail_template.py
diff options
context:
space:
mode:
authorThibault Delavallée <tde@odoo.com>2020-02-25 11:49:27 +0000
committerThibault Delavallée <tde@odoo.com>2020-03-24 10:24:19 +0000
commit822f468059c9702b0898016e7bfbaf036a2c4036 (patch)
tree819a2fea2e95860120b5e556aaca3a326003ac2c /addons/mail/models/mail_template.py
parenta03f6483d6be83a81eac6e8f667ce317c8007dbe (diff)
[MOV] mail: move rendering code to mail render mixin
We also have to update code calling directly the rendering itself. Indeed some code bits does some rendering directly on jinja-enabled input and not through templates. Those calls have to be updated accordingly. LINKS Task ID 1963529 Community PR odoo/odoo#32397
Diffstat (limited to 'addons/mail/models/mail_template.py')
-rw-r--r--addons/mail/models/mail_template.py174
1 files changed, 0 insertions, 174 deletions
diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py
index df14bfef5f7..72183aabf01 100644
--- a/addons/mail/models/mail_template.py
+++ b/addons/mail/models/mail_template.py
@@ -1,15 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import babel
import base64
-import copy
-import datetime
-import dateutil.relativedelta as relativedelta
-import functools
import logging
-from werkzeug import urls
from odoo import _, api, fields, models, tools
from odoo.exceptions import UserError
@@ -17,66 +11,6 @@ from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
-def format_date(env, date, pattern=False, lang_code=False):
- try:
- return tools.format_date(env, date, date_format=pattern, lang_code=lang_code)
- except babel.core.UnknownLocaleError:
- return date
-
-
-def format_datetime(env, dt, tz=False, dt_format='medium', lang_code=False):
- try:
- return tools.format_datetime(env, dt, tz=tz, dt_format=dt_format, lang_code=lang_code)
- except babel.core.UnknownLocaleError:
- return dt
-
-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
- jinja_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
- )
- jinja_template_env.globals.update({
- 'str': str,
- 'quote': urls.url_quote,
- 'urlencode': urls.url_encode,
- 'datetime': datetime,
- 'len': len,
- 'abs': abs,
- 'min': min,
- 'max': max,
- 'sum': sum,
- 'filter': filter,
- 'reduce': functools.reduce,
- 'map': map,
- 'round': round,
-
- # dateutil.relativedelta is an old-style class and cannot be directly
- # instanciated wihtin a jinja2 expression, so a lambda "proxy" is
- # is needed, apparently.
- 'relativedelta': lambda *a, **kw : relativedelta.relativedelta(*a, **kw),
- })
- jinja_safe_template_env = copy.copy(jinja_template_env)
- jinja_safe_template_env.autoescape = False
-except ImportError:
- _logger.warning("jinja2 not available, templating features will not work!")
-
-
class MailTemplate(models.Model):
"Templates for sending email"
_name = "mail.template"
@@ -180,114 +114,6 @@ class MailTemplate(models.Model):
# RENDERING
# ------------------------------------------------------------
- @api.model
- def _render_jinja_eval_context(self):
- """ Prepare jinja evaluation context, containing for all rendering
-
- * ``user``: current user browse record;
- * ``ctx```: current context, named ctx to avoid clash with jinja
- internals that already uses context;
- * various formatting tools;
- """
- render_context = {
- 'format_date': lambda date, date_format=False, lang_code=False: format_date(self.env, date, date_format, lang_code),
- 'format_datetime': lambda dt, tz=False, dt_format=False, lang_code=False: format_datetime(self.env, dt, tz, dt_format, lang_code),
- 'format_amount': lambda amount, currency, lang_code=False: tools.format_amount(self.env, amount, currency, lang_code),
- 'format_duration': lambda value: tools.format_duration(value),
- 'user': self.env.user,
- 'ctx': self._context,
- }
- return render_context
-
- @api.model
- def _render_template_jinja(self, template_txt, model, res_ids):
- """ Render a string-based template on records given by a model and a list
- of IDs, using jinja.
-
- In addition to the generic evaluation context given by _render_jinja_eval_context
- some new variables are added, depending on each record
-
- * ``object``: record based on which the template is rendered;
-
- :param str template_txt: template text to render
- :param str model: model name of records on which we want to perform rendering
- :param list res_ids: list of ids of records (all belonging to same model)
-
- :return dict: {res_id: string of rendered template based on record}
- """
- # TDE FIXME: remove that brol (6dde919bb9850912f618b561cd2141bffe41340c)
- no_autoescape = self._context.get('safe')
- results = dict.fromkeys(res_ids, u"")
- if not template_txt:
- return results
-
- # try to load the template
- try:
- jinja_env = jinja_safe_template_env if no_autoescape else jinja_template_env
- template = jinja_env.from_string(tools.ustr(template_txt))
- except Exception:
- _logger.info("Failed to load template %r", template_txt, exc_info=True)
- return results
-
- # prepare template variables
- variables = self._render_jinja_eval_context()
- # TDE CHECKME
- # records = self.env[model].browse(it for it in res_ids if it) # filter to avoid browsing [None]
- if any(r is None for r in res_ids):
- raise ValueError(_('Unsuspected None'))
-
- for record in self.env[model].browse(res_ids):
- variables['object'] = record
- try:
- render_result = template.render(variables)
- except Exception as e:
- _logger.info("Failed to render template : %s" % e, exc_info=True)
- raise UserError(_("Failed to render template : %s") % e)
- if render_result == u"False":
- render_result = u""
- results[record.id] = render_result
-
- return results
-
- @api.model
- def _render_template_postprocess(self, rendered):
- """ Tool method for post processing. In this method we ensure local
- links ('/shop/Basil-1') are replaced by global links ('https://www.
- mygardin.com/hop/Basil-1').
-
- :param rendered: result of ``_render_template``
-
- :return dict: updated version of rendered
- """
- for res_id, html in rendered.items():
- rendered[res_id] = self.env['mail.thread']._replace_local_links(html)
- return rendered
-
- @api.model
- def _render_template(self, template_txt, model, res_ids, engine='jinja', post_process=False):
- """ Render the given string on records designed by model / res_ids using
- the given rendering engine. Currently only jinja is supported.
-
- :param str template_txt: template text to render
- :param str model: model name of records on which we want to perform rendering
- :param list res_ids: list of ids of records (all belonging to same model)
- :param string engine: jinja
- :param post_process: perform rendered str / html post processing (see
- ``_render_template_postprocess``)
-
- :return dict: {res_id: string of rendered template based on record}
- """
- if not isinstance(res_ids, (list, tuple)):
- raise ValueError(_('Template rendering should be called only using on a list of IDs.'))
- if engine != 'jinja':
- raise ValueError(_('Template rendering supports only jinja.'))
-
- rendered = self._render_template_jinja(template_txt, model, res_ids)
- if post_process:
- rendered = self._render_template_postprocess(rendered)
-
- return rendered
-
def _render_lang(self, res_ids):
""" Given some record ids, return the lang for each record based on
lang field of template or through specific context-based key.