diff --git a/django/template/base.py b/django/template/base.py index ee2e145c04..b974495c9c 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -533,9 +533,13 @@ class Parser: def extend_nodelist(self, nodelist, node, token): # Check that non-text nodes don't appear before an extends tag. if node.must_be_first and nodelist.contains_nontext: + if self.origin.template_name: + origin = repr(self.origin.template_name) + else: + origin = "the template" raise self.error( token, - "%r must be the first tag in the template." % node, + "{%% %s %%} must be the first tag in %s." % (token.contents, origin), ) if not isinstance(node, TextNode): nodelist.contains_nontext = True diff --git a/tests/template_tests/test_extends.py b/tests/template_tests/test_extends.py index ce1838654b..0d2a93468c 100644 --- a/tests/template_tests/test_extends.py +++ b/tests/template_tests/test_extends.py @@ -1,9 +1,9 @@ import os -from django.template import Context, Engine, TemplateDoesNotExist +from django.template import Context, Engine, TemplateDoesNotExist, TemplateSyntaxError from django.test import SimpleTestCase -from .utils import ROOT +from .utils import ROOT, setup RECURSIVE = os.path.join(ROOT, "recursive_templates") @@ -181,3 +181,17 @@ class ExtendsBehaviorTests(SimpleTestCase): ) template = engine.get_template("base.html") self.assertEqual(template.render(Context({})), "12AB") + + @setup( + {"index.html": "{% block content %}B{% endblock %}{% extends 'base.html' %}"} + ) + def test_extends_not_first_tag_in_extended_template(self): + msg = "{% extends 'base.html' %} must be the first tag in 'index.html'." + with self.assertRaisesMessage(TemplateSyntaxError, msg): + self.engine.get_template("index.html") + + def test_extends_not_first_tag_in_extended_template_from_string(self): + template_string = "{% block content %}B{% endblock %}{% extends 'base.html' %}" + msg = "{% extends 'base.html' %} must be the first tag in the template." + with self.assertRaisesMessage(TemplateSyntaxError, msg): + Engine().from_string(template_string)