The issue appears to be that `{% extends parent_name %}` does not get re-
evaluated when the variable changes, eg. from `email/app1.email` to
`email/app2.email`.
* The Engine uses `django.template.loaders.cached.Loader`
* The first time the template is loaded, the parent template is loaded
based on `parent_name` is loaded
* Subsequent emails load the template, but do not re-evaluate the
`extends`
If this is as-designed, how would one go about clearing out that cache. I
am using code like this (when setting up my test case) but it doesn't
appear to clear the cache, even though my `print()` debugging shows its
the same object (`<django.template.loaders.cached.Loader object at
0x113e99828>`_
{{{
for template in engines.all():
for loader in template.engine.template_loaders:
loader.reset()
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28825>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Old description:
> In django templating you can use `{% extends parent_name %}` to indicate
> that the template is derived from another. We use this feature along
> with django-templated-email to have different base email templates for
> white-label purposes.
>
> The issue appears to be that `{% extends parent_name %}` does not get re-
> evaluated when the variable changes, eg. from `email/app1.email` to
> `email/app2.email`.
>
> * The Engine uses `django.template.loaders.cached.Loader`
> * The first time the template is loaded, the parent template is loaded
> based on `parent_name` is loaded
> * Subsequent emails load the template, but do not re-evaluate the
> `extends`
>
> If this is as-designed, how would one go about clearing out that cache.
> I am using code like this (when setting up my test case) but it doesn't
> appear to clear the cache, even though my `print()` debugging shows its
> the same object (`<django.template.loaders.cached.Loader object at
> 0x113e99828>`_
>
> {{{
> for template in engines.all():
> for loader in template.engine.template_loaders:
> loader.reset()
> }}}
New description:
In django templating you can use `{% extends parent_name %}` to indicate
that the template is derived from another. We use this feature along with
django-templated-email to have different base email templates for white-
label purposes.
The issue appears to be that `{% extends parent_name %}` does not get re-
evaluated when the variable changes, eg. from `email/app1.email` to
`email/app2.email`.
* The Engine uses `django.template.loaders.cached.Loader`
* The first time the template is loaded, the parent template is loaded
based on `parent_name` is loaded
* Subsequent emails load the template, but do not re-evaluate the
`extends`
----
If this is as-designed, how would one go about clearing out that cache?
When setting up my test case I call the code below, but it doesn't appear
to clear the cache, even though my `print()` debugging shows its the same
object (`<django.template.loaders.cached.Loader object at 0x113e99828>`_
{{{
for template in engines.all():
for loader in template.engine.template_loaders:
loader.reset()
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/28825#comment:1>
Comment (by Tim Graham):
Please include more explicit steps to reproduce (that don't rely on a
third-party library, to rule out an issue there). Based on your report, I
tried the following change in Django's test suite but don't see a failure.
{{{
#!diff
diff --git a/tests/template_tests/syntax_tests/test_extends.py
b/tests/template_tests/syntax_tests/test_extends.py
index 5b0b8d1..b52a9d1 100644
--- a/tests/template_tests/syntax_tests/test_extends.py
+++ b/tests/template_tests/syntax_tests/test_extends.py
@@ -108,6 +108,8 @@ class InheritanceTests(SimpleTestCase):
"""
output = self.engine.render_to_string('inheritance06', {'foo':
'inheritance02'})
self.assertEqual(output, '1234')
+ output = self.engine.render_to_string('inheritance06', {'foo':
'inheritance01'})
+ self.assertEqual(output, '1&3_')
@setup(inheritance_templates)
def test_inheritance07(self):
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28825#comment:2>
Old description:
> In django templating you can use `{% extends parent_name %}` to indicate
> that the template is derived from another. We use this feature along
> with django-templated-email to have different base email templates for
> white-label purposes.
>
> The issue appears to be that `{% extends parent_name %}` does not get re-
> evaluated when the variable changes, eg. from `email/app1.email` to
> `email/app2.email`.
>
> * The Engine uses `django.template.loaders.cached.Loader`
> * The first time the template is loaded, the parent template is loaded
> based on `parent_name` is loaded
> * Subsequent emails load the template, but do not re-evaluate the
> `extends`
>
> ----
>
> If this is as-designed, how would one go about clearing out that cache?
> When setting up my test case I call the code below, but it doesn't
> appear to clear the cache, even though my `print()` debugging shows its
> the same object (`<django.template.loaders.cached.Loader object at
> 0x113e99828>`_
>
> {{{
> for template in engines.all():
> for loader in template.engine.template_loaders:
> loader.reset()
> }}}
New description:
In django templating you can use `{% extends parent_name %}` to indicate
that the template is derived from another. We use this feature along with
django-templated-email to have different base email templates for white-
label purposes.
The issue appears to be that `{% extends parent_name %}` does not get re-
evaluated when the variable changes, eg. from `email/app1.email` to
`email/app2.email`.
* The Engine uses `django.template.loaders.cached.Loader`
* The first time the template is loaded, the parent template is loaded
based on `parent_name` is loaded
* Subsequent emails load the template, but do not re-evaluate the
`extends`
----
If this is as-designed, how would one go about clearing out that cache?
When setting up my test case I call the code below, but it doesn't appear
to clear the cache, even though my `print()` debugging shows its the same
object (`<django.template.loaders.cached.Loader object at 0x113e99828>`_
{{{
for template in engines.all():
for loader in template.engine.template_loaders:
loader.reset()
for x in loader.loaders:
x.reset()
}}}
--
Comment (by Andrew):
It would be best to know, going in, if {extends} is actually *expected* to
act like a meta-{%include%} or if the template engine actually combines
the two.
I'll work on a better test case or sample project, but it'll probably be a
few days. I've not had any cause to ever pull down the source before, and
certainly don't know how write proper tests for it, i'm just investigating
templates for the first time now.
* we use the `django-templated-email` package to wrap doing it, but it
ends up in a `DjangoTemplates` processor.
The Base Email (`object_created.email`). The base template includes
`{%include%}` directives which seem to be re-evaluated each time, the
opposite of extends. My working theory is that somehow the two just get
combined on the *first run* and ever-after are the same template somehow
(even though I can't find the cache, or figure out who's doing it)
{{{
{% extends base_template %}{% load i18n %}
{% block subject_line %}{% blocktrans %}New Something Happened{%
endblocktrans %}{% endblock %}
{% block html_content %}
<h2 style="font-size:15px;">Dear {{ some_person }},</h2>
}}}
In the two tests I set the base_template to something different, and also
try to `reset()` all the loaders including the children of the
`cached.Loader`, to no affect.
{{{
context_goog = { base_template="email/google_template.email",
some_person="Wonko the Sane" }
context_amzn = { base_template="email/amazon_template.email",
some_person="Wonko the Sane" }
send_templated_email("object_created.email", context_goog)
...
django.template.loader.get_template('email/object_created.email')
uses engine: <django.template.backends.django.DjangoTemplates object at
0x108573668>
DjangoTemplates.get_template('email/object_created.email')
<django.template.engine.Engine object at 0x108d7a2e8>
.find_template('email/object_created.email')
loader=<django.template.loaders.cached.Loader object at 0x10b957ef0>
.find_template('email/google_template.email')
loader=<django.template.loaders.cached.Loader object at 0x10b957ef0>
.find_template('email/partials/contents-footer.html')
loader=<django.template.loaders.cached.Loader object at 0x10b957ef0>
send_templated_email("object_created.email", context_amzn)
...
django.template.loader.get_template('email/object_created.email')
uses engine: <django.template.backends.django.DjangoTemplates object at
0x108573668>
DjangoTemplates.get_template('email/object_created.email')
<django.template.engine.Engine object at 0x108d7a2e8>
.find_template('email/object_created.email')
loader=<django.template.loaders.cached.Loader object at 0x10b957ef0>
.find_template('email/partials/contents-footer.html')
loader=<django.template.loaders.cached.Loader object at 0x10b957ef0>
}}}
I hope that printf_trace stuff helps in evaluating what is going on. It
might take me a few days to formulate a test case (if I can) or make a new
project (if I can't) demonstrating what is going on.
--
Ticket URL: <https://code.djangoproject.com/ticket/28825#comment:3>
* status: new => closed
* resolution: => invalid
Comment:
Terribly sorry for wasting your time. I found the source of the problem
having to do with django-templated-email, and a fix for slightly broken
template loaders in v1.9. On reevaluation of the template, the system
would not remember the DIRS to search. The patch for this was what was
causing this issue, and with v1.11.2 + a new version of the library, all
works well again.
Again, sorry for the erroneous bug report.
--
Ticket URL: <https://code.djangoproject.com/ticket/28825#comment:4>