changeset 2676:da8f3ac86845

template: overriden get_template to always have full template name: Environment.get_template has been overriden to have always full template name (i.e. template with (site/theme) prefix or absolute template). This is needed to correctly handle cache, so "base/base.html" is converted to "(some_site/some_theme)base/base.html" and won't conflict with an other theme "base/base.html".
author Goffi <goffi@goffi.org>
date Tue, 18 Sep 2018 20:59:34 +0200
parents 39d187f3698d
children 12620b10b20a
files sat/tools/common/template.py
diffstat 1 files changed, 30 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/sat/tools/common/template.py	Tue Sep 18 20:55:58 2018 +0200
+++ b/sat/tools/common/template.py	Tue Sep 18 20:59:34 2018 +0200
@@ -313,6 +313,23 @@
         return safe(u"\n".join(scripts))
 
 
+class Environment(jinja2.Environment):
+
+    def get_template(self, name, parent=None, globals=None):
+        if name[0] not in (u'/', u'('):
+            # if name is not an absolute path or a full template name (this happen on
+            # extend or import during rendering), we convert it to a full template name.
+            # This is needed to handle cache correctly when a base template is overriden.
+            # Without that, we could not distinguish something like base/base.html if
+            # it's launched from some_site/some_theme or from [default]/default
+            name = u"({site}/{theme}){template}".format(
+                site=self._template_data.site,
+                theme=self._template_data.theme,
+                template=name)
+
+        return super(Environment, self).get_template(name, parent, globals)
+
+
 class Renderer(object):
 
     def __init__(self, host, front_url_filter=None, trusted=False, private=False):
@@ -355,13 +372,14 @@
                 normalised[name] = path
             self.sites_paths.update(normalised)
 
-        self.env = jinja2.Environment(
+        self.env = Environment(
             loader=TemplateLoader(sites_paths=self.sites_paths, trusted=trusted),
             autoescape=jinja2.select_autoescape(["html", "xhtml", "xml"]),
             trim_blocks=True,
             lstrip_blocks=True,
             extensions=["jinja2.ext.i18n"],
         )
+        self.env._template_data = None
         self._locale_str = C.DEFAULT_LOCALE
         self._locale = Locale.parse(self._locale_str)
         self.installTranslations()
@@ -831,6 +849,13 @@
         else:
             template_data = self.env.loader.parse_template(template)
 
+        # we need to save template_data in environment, to load right templates when they
+        # are referenced from other templates (e.g. import)
+        # FIXME: this trick will not work anymore if we use async templates (it works
+        #        here because we know that the rendering will be blocking until we unset
+        #        _template_data)
+        self.env._template_data = template_data
+
         template_source = self.env.get_template(template)
 
         if css_files is None:
@@ -853,9 +878,10 @@
 
         scripts_handler = ScriptsHandler(self, template_data)
         self.setLocale(locale)
+
         # XXX: theme used in template arguments is the requested theme, which may differ
         #      from actual theme if the template doesn't exist in the requested theme.
-        return template_source.render(
+        rendered = template_source.render(
             template_data=template_data,
             media_path=media_path,
             css_files=css_files,
@@ -865,3 +891,5 @@
             script=scripts_handler,
             **kwargs
         )
+        self.env._template_data = None
+        return rendered