Opened 2 days ago

Last modified 40 hours ago

#36271 assigned Bug

{% 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: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
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

According to the ticket's flags, the next step(s) to move this issue forward are:

  • To improve the patch as described in the pull request review comments or on this ticket, then uncheck "Patch needs improvement".
  • If creating a new pull request, include a link to the pull request in the ticket comment when making that update. The usual format is: [https://github.com/django/django/pull/#### PR].

Change History (5)

by Yogya Chugh , 2 days ago

Attachment: test_case.py added

comment:1 by Sarah Boyce, 2 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 , 44 hours 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 , 41 hours ago

Has patch: set
Last edited 41 hours ago by Yogya Chugh (previous) (diff)

comment:4 by Sarah Boyce, 40 hours ago

Patch needs improvement: set
Note: See TracTickets for help on using tickets.
Back to Top