Opened 6 months ago
Last modified 3 months ago
#35493 assigned Bug
Allow `./` and `../` in paths when recursively including templates — at Initial Version
Reported by: | Gabriel Nick Pivovarov | Owned by: | nobody |
---|---|---|---|
Component: | Template system | Version: | 5.0 |
Severity: | Normal | Keywords: | template |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | yes | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
Hi. Currently, when trying to recursively include a Django template within itself using the include
tag with a path that contains ./
or ../
, Django raises a TemplateSyntaxError
. However, using a path that does not contain ./
or ../
does not raise the error. When the error is raised, the debug toolbar describes it like this:
TemplateSyntaxError at /
The relative path ‘“./ul.html”’ was translated to template name ‘app/ul.html’, the same template in which the tag appears.
Here is an example of a template in a Django app called app
with the path app/templates/app/ul.html
that would produce the error given above:
<ul> {% for section in sections %} <li> <p>{{ section.name }}</p> {% if section.sections|length != 0 %} {% include "./ul.html" with sections=section.sections %} {% endif %} </li> {% endfor %} </ul>
However, replacing the directory ./ul.html
with the equivalent app/ul.html
makes the error go away (assuming that the project's settings.py
specifies APP_DIRS = True
and the views and URLs are configured correctly). The actual paths are translated identically in both cases, and the behavior of the include
tag should not depend simply on whether or not the path string uses ./
or ../
(or if it should, this is not documented in the Django documentation). Therefore, it seems that this is a bug. The expected behavior is that an error is only raised when recursively using the extends
template, not when recursively using the include
template.
Contrapositively, it appears that recursively extending a template using the extends
tag with a path that does not contain ./
or ../
raises a TemplateDoesNotExist
exception, which is semantically inaccurate since the template is referencing itself and therefore necessarily exists.
One possible fix is to modify the django/template/loader_tags.py
file (https://github.com/django/django/blob/main/django/template/loader_tags.py) such that the error is raised when a template attempts to extend itself (not when a template attempts to include itself, which would otherwise be valid). The error handling logic in question starts on line 267 of that file within the construct_relative_path
function; perhaps it should live somewhere in the do_extends
function instead.
Here is a relevant discussion in the Django forums: https://forum.djangoproject.com/t/template-recursion-why-does-django-not-allow-and/31689