Skip to content

Commit c99f787

Browse files
mihalikvVinit Kumar
andauthored
fix: Fixed RecursionError when extending templates (django-cms#7594)
* fix: Fixed RecursionError when extending templates with higher depth * triv: sort imports * triv: imports sort * triv: run ruff cms * triv: changed import to import from * triv: run ruff cms --------- Co-authored-by: viliam mihalik <viliam.mihalik@smartbase.sk> Co-authored-by: Vinit Kumar <vinit.kumar@kidskonnect.nl>
1 parent ce4c299 commit c99f787

File tree

6 files changed

+76
-8
lines changed

6 files changed

+76
-8
lines changed

cms/test_utils/project/placeholderapp/nested_placeholderapp/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{% extends "placeholder_tests/nested_extend.html" %}
2+
3+
{% load cms_tags %}
4+
5+
{% comment %}
6+
This file should result in following placeholders:
7+
8+
- recursed_one (from cms/test_utils/project/placeholderapp/nested_placeholderapp/templates/placeholder_tests/nested_extend.html)
9+
- two (from cms/test_utils/project/placeholderapp/templates/placeholder_tests/nested_extend.html)
10+
- recursed_three (from cms/test_utils/project/placeholderapp/templates/placeholder_tests/nested_extend.html)
11+
12+
{% endcomment %}
13+
14+
{% block one %}
15+
{% placeholder "recursed_one" %}
16+
{% endblock %}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{% extends "placeholder_tests/nested_extend.html" %}
2+
3+
{% load cms_tags %}
4+
5+
{% comment %}
6+
This file should result in following placeholders:
7+
8+
- recursed_one (from cms/test_utils/project/placeholderapp/nested_placeholderapp/templates/placeholder_tests/nested_extend.html)
9+
- two (from cms/test_utils/project/placeholderapp/templates/placeholder_tests/nested_extend.html)
10+
- recursed_three (from cms/test_utils/project/placeholderapp/templates/placeholder_tests/nested_extend.html)
11+
12+
{% endcomment %}
13+
14+
{% block three %}
15+
{% placeholder "recursed_three" %}
16+
{% endblock %}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{% load cms_tags %}
2+
3+
{% block one %}
4+
{% placeholder "one" %}
5+
{% endblock %}
6+
7+
{% block two %}
8+
{% placeholder "two" %}
9+
{% endblock %}
10+
11+
{% block three %}
12+
{% placeholder "three" %}
13+
{% endblock %}
14+
15+
{% block four %}{% endblock %}

cms/tests/test_placeholder.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import copy
2+
import os
3+
14
from django.conf import settings
25
from django.contrib.auth import get_user_model
36
from django.core.cache import cache
@@ -10,6 +13,7 @@
1013
from django.utils.numberformat import format
1114
from sekizai.context import SekizaiContext
1215

16+
from cms import __file__ as cms_root_path
1317
from cms import constants
1418
from cms.api import add_plugin, create_page, create_title
1519
from cms.exceptions import DuplicatePlaceholderWarning, PluginLimitReached
@@ -116,6 +120,19 @@ def test_placeholder_recursive_extend(self):
116120
placeholders = _get_placeholder_slots('placeholder_tests/recursive_extend.html')
117121
self.assertEqual(sorted(placeholders), sorted(['recursed_one', 'recursed_two', 'three']))
118122

123+
def test_placeholder_recursive_deeper_extend(self):
124+
template_settings = copy.deepcopy(settings.TEMPLATES)
125+
cms_root_dir = os.path.dirname(cms_root_path)
126+
template_settings[0]["DIRS"] = [
127+
os.path.join(cms_root_dir, 'test_utils', 'project', 'placeholderapp',
128+
'nested_placeholderapp', 'templates'),
129+
os.path.join(cms_root_dir, 'test_utils', 'project', 'placeholderapp', 'templates'),
130+
os.path.join(cms_root_dir, 'test_utils', 'project', 'templates'),
131+
]
132+
with override_settings(TEMPLATES=template_settings):
133+
placeholders = _get_placeholder_slots('placeholder_tests/nested_extend.html')
134+
self.assertEqual(sorted(placeholders), sorted(['recursed_one', 'two', 'recursed_three']))
135+
119136
def test_placeholder_scanning_sekizai_extend_outside_block(self):
120137
placeholders = _get_placeholder_slots('placeholder_tests/outside_sekizai.html')
121138
self.assertEqual(sorted(placeholders), sorted(['new_one', 'two', 'base_outside']))

cms/utils/placeholder.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -273,16 +273,18 @@ def get_static_placeholders(template, context):
273273
return placeholders_with_code
274274

275275

276-
def _get_block_nodes(extend_node):
277-
parent = extend_node.get_parent(get_context(extend_node))
276+
def _get_block_nodes(extend_node, previous_context=None):
277+
if not previous_context:
278+
previous_context = get_context(extend_node)
279+
parent = extend_node.get_parent(previous_context)
278280
parent_nodelist = _get_nodelist(parent)
279281
parent_nodes = parent_nodelist.get_nodes_by_type(BlockNode)
280282
parent_extend_nodes = parent_nodelist.get_nodes_by_type(ExtendsNode)
281283

282284
if parent_extend_nodes:
283285
# Start at the top
284286
# Scan the extends node from the parent (if any)
285-
nodes = _get_block_nodes(parent_extend_nodes[0])
287+
nodes = _get_block_nodes(parent_extend_nodes[0], previous_context=previous_context)
286288
else:
287289
nodes = OrderedDict()
288290

@@ -322,10 +324,12 @@ def _get_placeholder_nodes_from_extend(extend_node, node_class):
322324
return placeholders
323325

324326

325-
def _find_topmost_template(extend_node):
326-
parent_template = extend_node.get_parent(get_context(extend_node))
327+
def _find_topmost_template(extend_node, previous_context=None):
328+
if not previous_context:
329+
previous_context = get_context(extend_node)
330+
parent_template = extend_node.get_parent(previous_context)
327331
for node in _get_nodelist(parent_template).get_nodes_by_type(ExtendsNode):
328332
# Their can only be one extend block in a template, otherwise django raises an exception
329-
return _find_topmost_template(node)
330-
# No ExtendsNode
331-
return extend_node.get_parent(get_context(extend_node))
333+
return _find_topmost_template(node, previous_context=previous_context)
334+
# No ExtendsNode
335+
return parent_template

0 commit comments

Comments
 (0)