2015-02-22 03:11:20 +08:00
|
|
|
from django.template import (
|
2017-02-11 19:51:57 +08:00
|
|
|
Context, Engine, TemplateDoesNotExist, TemplateSyntaxError, loader,
|
2015-02-22 03:11:20 +08:00
|
|
|
)
|
2017-09-03 08:24:01 +08:00
|
|
|
from django.test import SimpleTestCase
|
2014-11-12 09:32:44 +08:00
|
|
|
|
2015-01-28 20:35:27 +08:00
|
|
|
from .test_basic import basic_templates
|
2019-02-25 18:03:30 +08:00
|
|
|
from ..utils import setup
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
include_fail_templates = {
|
|
|
|
'include-fail1': '{% load bad_tag %}{% badtag %}',
|
|
|
|
'include-fail2': '{% load broken_tag %}',
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-04 04:36:17 +08:00
|
|
|
class IncludeTagTests(SimpleTestCase):
|
2015-05-09 04:10:36 +08:00
|
|
|
libraries = {'bad_tag': 'template_tests.templatetags.bad_tag'}
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include01': '{% include "basic-syntax01" %}'}, basic_templates)
|
|
|
|
def test_include01(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include01')
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'something cool')
|
|
|
|
|
|
|
|
@setup({'include02': '{% include "basic-syntax02" %}'}, basic_templates)
|
|
|
|
def test_include02(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include02', {'headline': 'Included'})
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'Included')
|
|
|
|
|
|
|
|
@setup({'include03': '{% include template_name %}'}, basic_templates)
|
|
|
|
def test_include03(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string(
|
2014-11-12 09:32:44 +08:00
|
|
|
'include03',
|
|
|
|
{'template_name': 'basic-syntax02', 'headline': 'Included'},
|
|
|
|
)
|
|
|
|
self.assertEqual(output, 'Included')
|
|
|
|
|
|
|
|
@setup({'include04': 'a{% include "nonexistent" %}b'})
|
|
|
|
def test_include04(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
template = self.engine.get_template('include04')
|
2017-09-03 08:24:01 +08:00
|
|
|
with self.assertRaises(TemplateDoesNotExist):
|
|
|
|
template.render(Context({}))
|
2016-09-09 09:24:22 +08:00
|
|
|
|
2014-11-12 09:32:44 +08:00
|
|
|
@setup({
|
|
|
|
'include 05': 'template with a space',
|
|
|
|
'include06': '{% include "include 05"%}',
|
|
|
|
})
|
|
|
|
def test_include06(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include06')
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, "template with a space")
|
|
|
|
|
|
|
|
@setup({'include07': '{% include "basic-syntax02" with headline="Inline" %}'}, basic_templates)
|
|
|
|
def test_include07(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include07', {'headline': 'Included'})
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'Inline')
|
|
|
|
|
|
|
|
@setup({'include08': '{% include headline with headline="Dynamic" %}'}, basic_templates)
|
|
|
|
def test_include08(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include08', {'headline': 'basic-syntax02'})
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'Dynamic')
|
|
|
|
|
|
|
|
@setup(
|
|
|
|
{'include09': '{{ first }}--'
|
|
|
|
'{% include "basic-syntax03" with first=second|lower|upper second=first|upper %}'
|
|
|
|
'--{{ second }}'},
|
|
|
|
basic_templates,
|
|
|
|
)
|
|
|
|
def test_include09(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include09', {'first': 'Ul', 'second': 'lU'})
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'Ul--LU --- UL--lU')
|
|
|
|
|
|
|
|
@setup({'include10': '{% include "basic-syntax03" only %}'}, basic_templates)
|
|
|
|
def test_include10(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include10', {'first': '1'})
|
|
|
|
if self.engine.string_if_invalid:
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'INVALID --- INVALID')
|
|
|
|
else:
|
|
|
|
self.assertEqual(output, ' --- ')
|
|
|
|
|
|
|
|
@setup({'include11': '{% include "basic-syntax03" only with second=2 %}'}, basic_templates)
|
|
|
|
def test_include11(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include11', {'first': '1'})
|
|
|
|
if self.engine.string_if_invalid:
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, 'INVALID --- 2')
|
|
|
|
else:
|
|
|
|
self.assertEqual(output, ' --- 2')
|
|
|
|
|
|
|
|
@setup({'include12': '{% include "basic-syntax03" with first=1 only %}'}, basic_templates)
|
|
|
|
def test_include12(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include12', {'second': '2'})
|
|
|
|
if self.engine.string_if_invalid:
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, '1 --- INVALID')
|
|
|
|
else:
|
|
|
|
self.assertEqual(output, '1 --- ')
|
|
|
|
|
|
|
|
@setup(
|
|
|
|
{'include13': '{% autoescape off %}{% include "basic-syntax03" %}{% endautoescape %}'},
|
|
|
|
basic_templates,
|
|
|
|
)
|
|
|
|
def test_include13(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include13', {'first': '&'})
|
|
|
|
if self.engine.string_if_invalid:
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, '& --- INVALID')
|
|
|
|
else:
|
|
|
|
self.assertEqual(output, '& --- ')
|
|
|
|
|
|
|
|
@setup(
|
|
|
|
{'include14': '{% autoescape off %}'
|
|
|
|
'{% include "basic-syntax03" with first=var1 only %}'
|
|
|
|
'{% endautoescape %}'},
|
|
|
|
basic_templates,
|
|
|
|
)
|
|
|
|
def test_include14(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
output = self.engine.render_to_string('include14', {'var1': '&'})
|
|
|
|
if self.engine.string_if_invalid:
|
2014-11-12 09:32:44 +08:00
|
|
|
self.assertEqual(output, '& --- INVALID')
|
|
|
|
else:
|
|
|
|
self.assertEqual(output, '& --- ')
|
|
|
|
|
|
|
|
# Include syntax errors
|
|
|
|
@setup({'include-error01': '{% include "basic-syntax01" with %}'})
|
|
|
|
def test_include_error01(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-error01')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error02': '{% include "basic-syntax01" with "no key" %}'})
|
|
|
|
def test_include_error02(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-error02')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error03': '{% include "basic-syntax01" with dotted.arg="error" %}'})
|
|
|
|
def test_include_error03(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-error03')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error04': '{% include "basic-syntax01" something_random %}'})
|
|
|
|
def test_include_error04(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-error04')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error05': '{% include "basic-syntax01" foo="duplicate" foo="key" %}'})
|
|
|
|
def test_include_error05(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-error05')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error06': '{% include "basic-syntax01" only only %}'})
|
|
|
|
def test_include_error06(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-error06')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup(include_fail_templates)
|
|
|
|
def test_include_fail1(self):
|
|
|
|
with self.assertRaises(RuntimeError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-fail1')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup(include_fail_templates)
|
|
|
|
def test_include_fail2(self):
|
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
2014-12-07 16:43:10 +08:00
|
|
|
self.engine.get_template('include-fail2')
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error07': '{% include "include-fail1" %}'}, include_fail_templates)
|
|
|
|
def test_include_error07(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
template = self.engine.get_template('include-error07')
|
2017-09-03 08:24:01 +08:00
|
|
|
with self.assertRaises(RuntimeError):
|
|
|
|
template.render(Context())
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error08': '{% include "include-fail2" %}'}, include_fail_templates)
|
|
|
|
def test_include_error08(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
template = self.engine.get_template('include-error08')
|
2017-09-03 08:24:01 +08:00
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
|
|
|
template.render(Context())
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error09': '{% include failed_include %}'}, include_fail_templates)
|
|
|
|
def test_include_error09(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
context = Context({'failed_include': 'include-fail1'})
|
|
|
|
template = self.engine.get_template('include-error09')
|
2017-09-03 08:24:01 +08:00
|
|
|
with self.assertRaises(RuntimeError):
|
|
|
|
template.render(context)
|
2014-11-12 09:32:44 +08:00
|
|
|
|
|
|
|
@setup({'include-error10': '{% include failed_include %}'}, include_fail_templates)
|
|
|
|
def test_include_error10(self):
|
2014-12-07 16:43:10 +08:00
|
|
|
context = Context({'failed_include': 'include-fail2'})
|
|
|
|
template = self.engine.get_template('include-error10')
|
2017-09-03 08:24:01 +08:00
|
|
|
with self.assertRaises(TemplateSyntaxError):
|
|
|
|
template.render(context)
|
2015-02-22 03:11:20 +08:00
|
|
|
|
2018-03-25 04:38:20 +08:00
|
|
|
@setup({'include_empty': '{% include %}'})
|
|
|
|
def test_include_empty(self):
|
|
|
|
msg = (
|
|
|
|
"'include' tag takes at least one argument: the name of the "
|
|
|
|
"template to be included."
|
|
|
|
)
|
|
|
|
with self.assertRaisesMessage(TemplateSyntaxError, msg):
|
|
|
|
self.engine.get_template('include_empty')
|
|
|
|
|
2015-02-22 03:11:20 +08:00
|
|
|
|
|
|
|
class IncludeTests(SimpleTestCase):
|
|
|
|
|
|
|
|
def test_include_missing_template(self):
|
|
|
|
"""
|
2016-10-27 15:53:39 +08:00
|
|
|
The correct template is identified as not existing
|
2015-02-22 03:11:20 +08:00
|
|
|
when {% include %} specifies a template that does not exist.
|
|
|
|
"""
|
2015-04-12 07:41:45 +08:00
|
|
|
engine = Engine(app_dirs=True, debug=True)
|
|
|
|
template = engine.get_template('test_include_error.html')
|
2015-02-22 03:11:20 +08:00
|
|
|
with self.assertRaises(TemplateDoesNotExist) as e:
|
2015-04-12 07:41:45 +08:00
|
|
|
template.render(Context())
|
2015-02-22 03:11:20 +08:00
|
|
|
self.assertEqual(e.exception.args[0], 'missing.html')
|
|
|
|
|
|
|
|
def test_extends_include_missing_baseloader(self):
|
|
|
|
"""
|
2016-10-27 15:53:39 +08:00
|
|
|
#12787 -- The correct template is identified as not existing
|
2015-02-22 03:11:20 +08:00
|
|
|
when {% extends %} specifies a template that does exist, but that
|
|
|
|
template has an {% include %} of something that does not exist.
|
|
|
|
"""
|
2015-04-12 07:41:45 +08:00
|
|
|
engine = Engine(app_dirs=True, debug=True)
|
|
|
|
template = engine.get_template('test_extends_error.html')
|
2015-02-22 03:11:20 +08:00
|
|
|
with self.assertRaises(TemplateDoesNotExist) as e:
|
2015-04-12 07:41:45 +08:00
|
|
|
template.render(Context())
|
2015-02-22 03:11:20 +08:00
|
|
|
self.assertEqual(e.exception.args[0], 'missing.html')
|
|
|
|
|
|
|
|
def test_extends_include_missing_cachedloader(self):
|
2015-04-12 07:41:45 +08:00
|
|
|
engine = Engine(debug=True, loaders=[
|
|
|
|
('django.template.loaders.cached.Loader', [
|
|
|
|
'django.template.loaders.app_directories.Loader',
|
|
|
|
]),
|
|
|
|
])
|
2015-02-22 03:11:20 +08:00
|
|
|
|
2015-04-12 07:41:45 +08:00
|
|
|
template = engine.get_template('test_extends_error.html')
|
2015-02-22 03:11:20 +08:00
|
|
|
with self.assertRaises(TemplateDoesNotExist) as e:
|
2015-04-12 07:41:45 +08:00
|
|
|
template.render(Context())
|
2015-02-22 03:11:20 +08:00
|
|
|
self.assertEqual(e.exception.args[0], 'missing.html')
|
|
|
|
|
|
|
|
# Repeat to ensure it still works when loading from the cache
|
2015-04-12 07:41:45 +08:00
|
|
|
template = engine.get_template('test_extends_error.html')
|
2015-02-22 03:11:20 +08:00
|
|
|
with self.assertRaises(TemplateDoesNotExist) as e:
|
2015-04-12 07:41:45 +08:00
|
|
|
template.render(Context())
|
2015-02-22 03:11:20 +08:00
|
|
|
self.assertEqual(e.exception.args[0], 'missing.html')
|
|
|
|
|
|
|
|
def test_include_template_argument(self):
|
|
|
|
"""
|
|
|
|
Support any render() supporting object
|
|
|
|
"""
|
2015-04-12 07:41:45 +08:00
|
|
|
engine = Engine()
|
2015-02-22 03:11:20 +08:00
|
|
|
ctx = Context({
|
2015-04-12 07:41:45 +08:00
|
|
|
'tmpl': engine.from_string('This worked!'),
|
2015-02-22 03:11:20 +08:00
|
|
|
})
|
2015-04-12 07:41:45 +08:00
|
|
|
outer_tmpl = engine.from_string('{% include tmpl %}')
|
2015-02-22 03:11:20 +08:00
|
|
|
output = outer_tmpl.render(ctx)
|
|
|
|
self.assertEqual(output, 'This worked!')
|
|
|
|
|
2017-02-11 19:51:57 +08:00
|
|
|
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')})
|
|
|
|
self.assertEqual(output, 'index\n\n')
|
|
|
|
|
2015-02-22 03:11:20 +08:00
|
|
|
def test_include_immediate_missing(self):
|
|
|
|
"""
|
|
|
|
#16417 -- Include tags pointing to missing templates should not raise
|
|
|
|
an error at parsing time.
|
|
|
|
"""
|
2015-04-12 07:41:45 +08:00
|
|
|
Engine(debug=True).from_string('{% include "this_does_not_exist.html" %}')
|
|
|
|
|
2015-02-22 03:11:20 +08:00
|
|
|
def test_include_recursive(self):
|
|
|
|
comments = [
|
|
|
|
{
|
|
|
|
'comment': 'A1',
|
|
|
|
'children': [
|
|
|
|
{'comment': 'B1', 'children': []},
|
|
|
|
{'comment': 'B2', 'children': []},
|
|
|
|
{'comment': 'B3', 'children': [
|
|
|
|
{'comment': 'C1', 'children': []}
|
|
|
|
]},
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
2015-04-12 07:41:45 +08:00
|
|
|
engine = Engine(app_dirs=True)
|
|
|
|
t = engine.get_template('recursive_include.html')
|
2015-02-22 03:11:20 +08:00
|
|
|
self.assertEqual(
|
|
|
|
"Recursion! A1 Recursion! B1 B2 B3 Recursion! C1",
|
2015-04-12 07:41:45 +08:00
|
|
|
t.render(Context({'comments': comments})).replace(' ', '').replace('\n', ' ').strip(),
|
2015-02-22 03:11:20 +08:00
|
|
|
)
|
2017-04-04 10:29:39 +08:00
|
|
|
|
|
|
|
def test_include_cache(self):
|
|
|
|
"""
|
|
|
|
{% include %} keeps resolved templates constant (#27974). The
|
|
|
|
CounterNode object in the {% counter %} template tag is created once
|
|
|
|
if caching works properly. Each iteration increases the counter instead
|
|
|
|
of restarting it.
|
|
|
|
|
|
|
|
This works as a regression test only if the cached loader
|
|
|
|
isn't used, so the @setup decorator isn't used.
|
|
|
|
"""
|
|
|
|
engine = Engine(loaders=[
|
|
|
|
('django.template.loaders.locmem.Loader', {
|
|
|
|
'template': '{% for x in vars %}{% include "include" %}{% endfor %}',
|
|
|
|
'include': '{% include "next" %}',
|
|
|
|
'next': '{% load custom %}{% counter %}'
|
|
|
|
}),
|
|
|
|
], libraries={'custom': 'template_tests.templatetags.custom'})
|
2017-06-02 07:08:59 +08:00
|
|
|
output = engine.render_to_string('template', {'vars': range(9)})
|
2017-04-04 10:29:39 +08:00
|
|
|
self.assertEqual(output, '012345678')
|