mirror of
https://github.com/django/django.git
synced 2024-12-22 09:05:43 +00:00
Fixed #35493 -- Allowed template self-inclusion with relative paths.
Co-authored-by: Brock <bsmick97@gmail.com>
This commit is contained in:
parent
ded4854642
commit
55855bc6d0
@ -242,7 +242,11 @@ def do_block(parser, token):
|
||||
return BlockNode(block_name, nodelist)
|
||||
|
||||
|
||||
def construct_relative_path(current_template_name, relative_name):
|
||||
def construct_relative_path(
|
||||
current_template_name,
|
||||
relative_name,
|
||||
allow_recursion=False,
|
||||
):
|
||||
"""
|
||||
Convert a relative path (starting with './' or '../') to the full template
|
||||
name based on the current_template_name.
|
||||
@ -264,7 +268,7 @@ def construct_relative_path(current_template_name, relative_name):
|
||||
"The relative path '%s' points outside the file hierarchy that "
|
||||
"template '%s' is in." % (relative_name, current_template_name)
|
||||
)
|
||||
if current_template_name.lstrip("/") == new_name:
|
||||
if not allow_recursion and current_template_name.lstrip("/") == new_name:
|
||||
raise TemplateSyntaxError(
|
||||
"The relative path '%s' was translated to template name '%s', the "
|
||||
"same template in which the tag appears."
|
||||
@ -346,7 +350,11 @@ def do_include(parser, token):
|
||||
options[option] = value
|
||||
isolated_context = options.get("only", False)
|
||||
namemap = options.get("with", {})
|
||||
bits[1] = construct_relative_path(parser.origin.template_name, bits[1])
|
||||
bits[1] = construct_relative_path(
|
||||
parser.origin.template_name,
|
||||
bits[1],
|
||||
allow_recursion=True,
|
||||
)
|
||||
return IncludeNode(
|
||||
parser.compile_filter(bits[1]),
|
||||
extra_context=namemap,
|
||||
|
@ -330,15 +330,43 @@ class IncludeTests(SimpleTestCase):
|
||||
],
|
||||
}
|
||||
]
|
||||
engine = Engine(app_dirs=True)
|
||||
t = engine.get_template("recursive_include.html")
|
||||
self.assertEqual(
|
||||
"Recursion! A1 Recursion! B1 B2 B3 Recursion! C1",
|
||||
t.render(Context({"comments": comments}))
|
||||
.replace(" ", "")
|
||||
.replace("\n", " ")
|
||||
.strip(),
|
||||
)
|
||||
with self.subTest(template="recursive_include.html"):
|
||||
engine = Engine(app_dirs=True)
|
||||
t = engine.get_template("recursive_include.html")
|
||||
self.assertEqual(
|
||||
"Recursion! A1 Recursion! B1 B2 B3 Recursion! C1",
|
||||
t.render(Context({"comments": comments}))
|
||||
.replace(" ", "")
|
||||
.replace("\n", " ")
|
||||
.strip(),
|
||||
)
|
||||
with self.subTest(template="recursive_relative_include.html"):
|
||||
engine = Engine(app_dirs=True)
|
||||
t = engine.get_template("recursive_relative_include.html")
|
||||
self.assertEqual(
|
||||
"Recursion! A1 Recursion! B1 B2 B3 Recursion! C1",
|
||||
t.render(Context({"comments": comments}))
|
||||
.replace(" ", "")
|
||||
.replace("\n", " ")
|
||||
.strip(),
|
||||
)
|
||||
with self.subTest(template="tmpl"):
|
||||
engine = Engine()
|
||||
template = """
|
||||
Recursion!
|
||||
{% for c in comments %}
|
||||
{{ c.comment }}
|
||||
{% if c.children %}{% include tmpl with comments=c.children %}{% endif %}
|
||||
{% endfor %}
|
||||
"""
|
||||
outer_tmpl = engine.from_string("{% include tmpl %}")
|
||||
output = outer_tmpl.render(
|
||||
Context({"tmpl": engine.from_string(template), "comments": comments})
|
||||
)
|
||||
self.assertEqual(
|
||||
"Recursion! A1 Recursion! B1 B2 B3 Recursion! C1",
|
||||
output.replace(" ", "").replace("\n", " ").strip(),
|
||||
)
|
||||
|
||||
def test_include_cache(self):
|
||||
"""
|
||||
|
@ -0,0 +1,7 @@
|
||||
Recursion!
|
||||
{% for comment in comments %}
|
||||
{{ comment.comment }}
|
||||
{% if comment.children %}
|
||||
{% include "./recursive_relative_include.html" with comments=comment.children %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
Loading…
Reference in New Issue
Block a user