Opened 6 days ago

Closed 2 days ago

#36271 closed Bug (fixed)

{% extends %} tag causes AttributeError if origin is None and path is relative

Reported by: Yogya Chugh Owned by: Yogya Chugh
Component: Template system Version: dev
Severity: Normal Keywords: extends
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

So while working on a ticket, I came across a strange behaviour that whenever I pass a relative path like './goa.html' to the extends tag that leads to an Attribution error !
I have attached a test case which will pass if error is produced ! You can check it out !
So, I tried to find the reason for this and found:-
When we separately create a Template and Context class along with calling the render method of Template, the error is produced.

This happens because in such a case the origin for the template is None hence, setting it to '<unknown source>' due to this code:-

#django/template/base.py
if origin is None:
    origin = Origin(UNKNOWN_SOURCE)

Here, UNKNOWN_SOURCE is global variable with value "<unknown source>"

So this ain't an issue normally but when we use {% extends %} tag, it makes use of a function construct_relative_path which is passed the template name from origin !

The function construct_relative_path performs an lstrip method on the template leading to error in case the template's origin is "<unknown source>". Because, origin.template_name is None. And so does the lstrip method produces error .

Code Snippet:-

#django/template/loader_tags.py
new_name = posixpath.normpath(
        posixpath.join(
            posixpath.dirname(current_template_name.lstrip("/")),
            new_name,
        )
    )

The Error log:-

Internal Server Error: /
Traceback (most recent call last):
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Lenovo\OneDrive\Desktop\djangoplz\new\trial\views.py", line 9, in index
    temp = Template(temp_string)
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\template\base.py", line 154, in __init__
    self.nodelist = self.compile_nodelist()
                    ~~~~~~~~~~~~~~~~~~~~~^^
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\template\base.py", line 196, in compile_nodelist
    nodelist = parser.parse()
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\template\base.py", line 518, in parse
    raise self.error(token, e)
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\template\base.py", line 516, in parse
    compiled_result = compile_func(self, token)
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\template\loader_tags.py", line 293, in do_extends
    bits[1] = construct_relative_path(parser.origin.template_name, bits[1])
              ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Lenovo\AppData\Roaming\Python\Python313\site-packages\django\template\loader_tags.py", line 258, in construct_relative_path
    posixpath.dirname(current_template_name.lstrip("/")),
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'lstrip'

This error is produced on both 5.1.7 version and on the dev too !

I would love to work on this ! Please do review

Change History (7)

by Yogya Chugh , 6 days ago

Attachment: test_case.py added

comment:1 by Sarah Boyce, 6 days ago

Summary: {% extends %} tag causes error if origin is None and path is relative{% extends %} tag causes AttributeError if origin is None and path is relative
Triage Stage: UnreviewedAccepted

Thank you, replicated. I think this should be raising a TemplateDoesNotExist error instead similar to if the path was not relative

  • TabularUnified tests/template_tests/syntax_tests/test_exceptions.py

    a b  
    1 from django.template import TemplateDoesNotExist, TemplateSyntaxError
     1from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context, Template
    22from django.test import SimpleTestCase
    33
    44from ..utils import setup
    class ExceptionsTests(SimpleTestCase):  
    1414        with self.assertRaises(TemplateDoesNotExist):
    1515            self.engine.render_to_string("exception01")
    1616
     17    def test_template_does_not_exist(self):
     18        for template_name in ["nonexistent.html", "./nonexistent.html"]:
     19            with self.subTest(template_name=template_name):
     20                template = Template(f"{{% extends '{template_name}' %}}")
     21                with self.assertRaises(TemplateDoesNotExist):
     22                    template.render(Context({}))
     23
    1724    @setup({"exception02": "{% extends nonexistent %}"})
    1825    def test_exception02(self):

comment:2 by Yogya Chugh , 5 days ago

Owner: set to Yogya Chugh
Status: newassigned

Yup ! I will add a check condition for None template name in construct_relative_path and add test case for when the template do exist !

comment:3 by Yogya Chugh , 5 days ago

Has patch: set
Version 0, edited 5 days ago by Yogya Chugh (next)

comment:4 by Sarah Boyce, 5 days ago

Patch needs improvement: set

comment:5 by Sarah Boyce, 2 days ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:6 by Sarah Boyce <42296566+sarahboyce@…>, 2 days ago

Resolution: fixed
Status: assignedclosed

In 7164f08:

Fixed #36271 -- Raised TemplateSyntaxError when using a relative template path with an unknown origin.

Note: See TracTickets for help on using tickets.
Back to Top