diff options
| author | farhan <farhanalirazaazeemi@gmail.com> | 2025-09-02 15:00:40 -0400 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2025-09-03 10:59:58 -0400 |
| commit | d82f25d3f0f4eb7be721a72d0e79a8d13d394d32 (patch) | |
| tree | 376c5b2eeb5252e3ea252d5d71e8952eff2c5c7f /django/template | |
| parent | 3485599ef08811e2fd066458aa083b2567f3cb84 (diff) | |
Fixed #36559 -- Respected verbatim and comment blocks in PartialTemplate.source.
Diffstat (limited to 'django/template')
| -rw-r--r-- | django/template/base.py | 34 | ||||
| -rw-r--r-- | django/template/defaulttags.py | 15 |
2 files changed, 27 insertions, 22 deletions
diff --git a/django/template/base.py b/django/template/base.py index d7bc59d668..37e7243d5c 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -89,11 +89,6 @@ UNKNOWN_SOURCE = "<unknown source>" # than instantiating SimpleLazyObject with _lazy_re_compile(). tag_re = re.compile(r"({%.*?%}|{{.*?}}|{#.*?#})") -combined_partial_re = re.compile( - r"{%\s*partialdef\s+(?P<name>[\w-]+)(?:\s+inline)?\s*%}" - r"|{%\s*endpartialdef(?:\s+[\w-]+)?\s*%}" -) - logger = logging.getLogger("django.template") @@ -301,29 +296,26 @@ class PartialTemplate: Wraps nodelist as a partial, in order to be able to bind context. """ - def __init__(self, nodelist, origin, name): + def __init__(self, nodelist, origin, name, source_start=None, source_end=None): self.nodelist = nodelist self.origin = origin self.name = name + # If available (debug mode), the absolute character offsets in the + # template.source correspond to the full partial region. + self._source_start = source_start + self._source_end = source_end def get_exception_info(self, exception, token): template = self.origin.loader.get_template(self.origin.template_name) return template.get_exception_info(exception, token) - def find_partial_source(self, full_source, partial_name): - start_match = None - nesting = 0 - - for match in combined_partial_re.finditer(full_source): - if name := match["name"]: # Opening tag. - if start_match is None and name == partial_name: - start_match = match - if start_match is not None: - nesting += 1 - elif start_match is not None: - nesting -= 1 - if nesting == 0: - return full_source[start_match.start() : match.end()] + def find_partial_source(self, full_source): + if ( + self._source_start is not None + and self._source_end is not None + and 0 <= self._source_start <= self._source_end <= len(full_source) + ): + return full_source[self._source_start : self._source_end] return "" @@ -337,7 +329,7 @@ class PartialTemplate: RuntimeWarning, stacklevel=2, ) - return self.find_partial_source(template.source, self.name) + return self.find_partial_source(template.source) def _render(self, context): return self.nodelist.render(context) diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 4cbaf852e1..ac3d5de901 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -1235,11 +1235,18 @@ def partialdef_func(parser, token): # Parse the content until the end tag. valid_endpartials = ("endpartialdef", f"endpartialdef {partial_name}") + + pos_open = getattr(token, "position", None) + source_start = pos_open[0] if isinstance(pos_open, tuple) else None + nodelist = parser.parse(valid_endpartials) endpartial = parser.next_token() if endpartial.contents not in valid_endpartials: parser.invalid_block_tag(endpartial, "endpartialdef", valid_endpartials) + pos_close = getattr(endpartial, "position", None) + source_end = pos_close[1] if isinstance(pos_close, tuple) else None + # Store the partial nodelist in the parser.extra_data attribute. partials = parser.extra_data.setdefault("partials", {}) if partial_name in partials: @@ -1247,7 +1254,13 @@ def partialdef_func(parser, token): f"Partial '{partial_name}' is already defined in the " f"'{parser.origin.name}' template." ) - partials[partial_name] = PartialTemplate(nodelist, parser.origin, partial_name) + partials[partial_name] = PartialTemplate( + nodelist, + parser.origin, + partial_name, + source_start=source_start, + source_end=source_end, + ) return PartialDefNode(partial_name, inline, nodelist) |
