Fixed #20995 -- Added support for iterables of template names to {% include %} template tag.

Thanks Adam Johnson for the review.
This commit is contained in:
Keshav Kumar 2020-02-02 22:18:07 +05:30 committed by Mariusz Felisiak
parent 8690878507
commit f37d548ede
4 changed files with 37 additions and 3 deletions

View File

@ -168,12 +168,16 @@ class IncludeNode(Node):
template = self.template.resolve(context)
# Does this quack like a Template?
if not callable(getattr(template, 'render', None)):
# If not, try the cache and get_template().
template_name = template
# If not, try the cache and select_template().
template_name = template or ()
if isinstance(template_name, str):
template_name = (template_name,)
else:
template_name = tuple(template_name)
cache = context.render_context.dicts[0].setdefault(self, {})
template = cache.get(template_name)
if template is None:
template = context.template.engine.get_template(template_name)
template = context.template.engine.select_template(template_name)
cache[template_name] = template
# Use the base.Template of a backends.django.Template.
elif hasattr(template, 'template'):

View File

@ -688,6 +688,10 @@ the variable ``template_name``::
The variable may also be any object with a ``render()`` method that accepts a
context. This allows you to reference a compiled ``Template`` in your context.
Additionally, the variable may be an iterable of template names, in which case
the first that can be loaded will be used, as per
:func:`~django.template.loader.select_template`.
An included template is rendered within the context of the template that
includes it. This example produces the output ``"Hello, John!"``:
@ -724,6 +728,10 @@ available to the included template::
been evaluated and rendered* - not blocks that can be overridden by, for
example, an extending template.
.. versionchanged:: 3.1
Support for iterables of template names was added.
.. templatetag:: load
``load``

View File

@ -322,6 +322,8 @@ Templates
and :ttag:`blocktrans` template tags aliases continue to work, and will be
retained for the foreseeable future.
* The :ttag:`include` template tag now accepts iterables of template names.
Tests
~~~~~

View File

@ -243,6 +243,26 @@ class IncludeTests(SimpleTestCase):
output = outer_tmpl.render(ctx)
self.assertEqual(output, 'This worked!')
def test_include_template_iterable(self):
engine = Engine.get_default()
outer_temp = engine.from_string('{% include var %}')
tests = [
('admin/fail.html', 'index.html'),
['admin/fail.html', 'index.html'],
]
for template_names in tests:
with self.subTest(template_names):
output = outer_temp.render(Context({'var': template_names}))
self.assertEqual(output, 'index\n')
def test_include_template_none(self):
engine = Engine.get_default()
outer_temp = engine.from_string('{% include var %}')
ctx = Context({'var': None})
msg = 'No template names provided'
with self.assertRaisesMessage(TemplateDoesNotExist, msg):
outer_temp.render(ctx)
def test_include_from_loader_get_template(self):
tmpl = loader.get_template('include_tpl.html') # {% include tmpl %}
output = tmpl.render({'tmpl': loader.get_template('index.html')})