mirror of
https://github.com/django-components/django-components.git
synced 2025-10-09 21:41:59 +00:00
refactor: fix compat with include and extends (#1441)
This commit is contained in:
parent
0be116c7b8
commit
5f0b7905c5
4 changed files with 88 additions and 2 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,7 +1,19 @@
|
|||
# Release notes
|
||||
|
||||
## v0.142.2
|
||||
|
||||
_06 Oct 2025_
|
||||
|
||||
#### Fix
|
||||
|
||||
- Fix compatibility issue when there was multiple `{% include %}` blocks
|
||||
inside a component fill, while those included templates contained `{% extends %}` tags.
|
||||
See [#1389](https://github.com/django-components/django-components/issues/1389)
|
||||
|
||||
## v0.142.1
|
||||
|
||||
_06 Oct 2025_
|
||||
|
||||
#### Fix
|
||||
|
||||
- Fix bug introduced in v0.142.0 where django-components broke
|
||||
|
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "django_components"
|
||||
version = "0.142.1"
|
||||
version = "0.142.2"
|
||||
requires-python = ">=3.8, <4.0"
|
||||
description = "A way to create simple reusable template components in Django."
|
||||
keywords = ["django", "components", "css", "js", "html"]
|
||||
|
|
|
@ -249,7 +249,14 @@ def monkeypatch_include_render(include_node_cls: Type[Node]) -> None:
|
|||
|
||||
# NOTE: This implementation is based on Django v5.1.3)
|
||||
def _include_render(self: IncludeNode, context: Context, *args: Any, **kwargs: Any) -> str:
|
||||
with context.update({_STRATEGY_CONTEXT_KEY: "ignore"}):
|
||||
# NOTE: `_STRATEGY_CONTEXT_KEY` is used so that we defer the rendering of components' JS/CSS
|
||||
# to until the parent template that used the `{% include %}` tag is rendered.
|
||||
# NOTE: `{ COMPONENT_IS_NESTED_KEY: False }` is used so that a new RenderContext layer is created,
|
||||
# so that inside each `{% include %}` the template can use the `{% extends %}` tag.
|
||||
# Otherwise, the state leaks, and if both `{% include %}` templates use the `{% extends %}` tag,
|
||||
# the second one raises, because it would be like using two `{% extends %}` tags in the same template.
|
||||
# See https://github.com/django-components/django-components/issues/1389
|
||||
with context.update({_STRATEGY_CONTEXT_KEY: "ignore", COMPONENT_IS_NESTED_KEY: False}):
|
||||
return orig_include_render(self, context, *args, **kwargs)
|
||||
|
||||
include_node_cls.render = _include_render
|
||||
|
|
|
@ -1075,3 +1075,70 @@ class TestExtendsCompat:
|
|||
<p data-djc-id-ca1bc40 data-djc-id-ca1bc42>This template extends another template.</p>
|
||||
""",
|
||||
)
|
||||
|
||||
@djc_test(parametrize=PARAMETRIZE_CONTEXT_BEHAVIOR)
|
||||
def test_double_include_template_with_extend(
|
||||
self,
|
||||
components_settings,
|
||||
):
|
||||
@register("simple_component")
|
||||
class SimpleComponent(Component):
|
||||
template: types.django_html = """
|
||||
{% slot 'content' / %}
|
||||
"""
|
||||
|
||||
# Confirm that this setup works in Django without components
|
||||
template1: types.django_html = """
|
||||
{% extends 'block.html' %}
|
||||
{% load component_tags %}
|
||||
{% block body %}
|
||||
{# history: [<Origin name='/Users/presenter/repos/django-components/tests/templates/included.html'>] #}
|
||||
{% include 'included.html' with variable="INCLUDED 1" %}
|
||||
{# history: [<Origin name='/Users/presenter/repos/django-components/tests/templates/included.html'>] #}
|
||||
{% include 'included.html' with variable="INCLUDED 2" %}
|
||||
{% endblock %}
|
||||
"""
|
||||
rendered1 = Template(template1).render(Context())
|
||||
expected1 = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<main role="main">
|
||||
<div class='container main-container'>
|
||||
Variable: <strong>INCLUDED 1</strong>
|
||||
Variable: <strong>INCLUDED 2</strong>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
assertHTMLEqual(rendered1, expected1)
|
||||
|
||||
template2: types.django_html = """
|
||||
{% extends 'block.html' %}
|
||||
{% load component_tags %}
|
||||
{% block body %}
|
||||
{% component "simple_component" %}
|
||||
{% fill "content" %}
|
||||
{% include 'included.html' with variable="INCLUDED 1" %}
|
||||
{% include 'included.html' with variable="INCLUDED 2" %}
|
||||
{% endfill %}
|
||||
{% endcomponent %}
|
||||
{% endblock %}
|
||||
"""
|
||||
rendered2 = Template(template2).render(Context({"DJC_DEPS_STRATEGY": "ignore"}))
|
||||
|
||||
expected2 = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<main role="main">
|
||||
<div class='container main-container'>
|
||||
Variable: <strong data-djc-id-ca1bc40="">INCLUDED 1</strong>
|
||||
Variable: <strong data-djc-id-ca1bc40="">INCLUDED 2</strong>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
assertHTMLEqual(rendered2, expected2)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue