fix: Set Context.template for components to work with include (#582)

This commit is contained in:
Juro Oravec 2024-08-16 23:31:00 +02:00 committed by GitHub
parent b2fece49d2
commit b8e92dac37
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 12 deletions

View file

@ -362,15 +362,11 @@ class Component(View, metaclass=ComponentMeta):
slots: Optional[Mapping[SlotName, SlotContent]] = None, slots: Optional[Mapping[SlotName, SlotContent]] = None,
escape_slots_content: bool = True, escape_slots_content: bool = True,
) -> str: ) -> str:
# Allow to provide no args/kwargs # Allow to provide no args/kwargs/slots/context
args = args or [] args = args or [] # type: ignore[assignment]
kwargs = kwargs or {} kwargs = kwargs or {} # type: ignore[assignment]
slots = slots or {} # type: ignore[assignment]
# Allow to provide no Context, so we can render component just with args + kwargs context = context or Context()
context_was_given = True
if context is None:
context = Context()
context_was_given = False
# Allow to provide a dict instead of Context # Allow to provide a dict instead of Context
# NOTE: This if/else is important to avoid nested Contexts, # NOTE: This if/else is important to avoid nested Contexts,
@ -387,9 +383,11 @@ class Component(View, metaclass=ComponentMeta):
with context.update(context_data): with context.update(context_data):
template = self.get_template(context) template = self.get_template(context)
_monkeypatch_template(template) _monkeypatch_template(template)
if not context_was_given:
if context.template is None:
# Associate the newly-created Context with a Template, otherwise we get # Associate the newly-created Context with a Template, otherwise we get
# an error when we try to use `{% include %}` tag inside the template? # an error when we try to use `{% include %}` tag inside the template?
# See https://github.com/EmilStenstrom/django-components/issues/580
context.template = template context.template = template
context.template_name = template.name context.template_name = template.name

View file

@ -6,8 +6,8 @@ For tests focusing on the `component` tag, see `test_templatetags_component.py`
from typing import Dict from typing import Dict
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponse from django.http import HttpRequest, HttpResponse
from django.template import Context, Template, TemplateSyntaxError from django.template import Context, RequestContext, Template, TemplateSyntaxError
from django_components import Component, registry, types from django_components import Component, registry, types
from django_components.slots import SlotRef from django_components.slots import SlotRef
@ -448,6 +448,50 @@ class ComponentRenderTest(BaseTestCase):
""", """,
) )
# See https://github.com/EmilStenstrom/django-components/issues/580
# And https://github.com/EmilStenstrom/django-components/commit/fee26ec1d8b46b5ee065ca1ce6143889b0f96764
@parametrize_context_behavior(["django", "isolated"])
def test_render_with_include_and_context(self):
class SimpleComponent(Component):
template: types.django_html = """
{% load component_tags %}
{% include 'slotted_template.html' %}
"""
rendered = SimpleComponent.render(context=Context())
self.assertHTMLEqual(
rendered,
"""
<custom-template>
<header>Default header</header>
<main>Default main</main>
<footer>Default footer</footer>
</custom-template>
""",
)
# See https://github.com/EmilStenstrom/django-components/issues/580
# And https://github.com/EmilStenstrom/django-components/commit/fee26ec1d8b46b5ee065ca1ce6143889b0f96764
@parametrize_context_behavior(["django", "isolated"])
def test_render_with_include_and_request_context(self):
class SimpleComponent(Component):
template: types.django_html = """
{% load component_tags %}
{% include 'slotted_template.html' %}
"""
rendered = SimpleComponent.render(context=RequestContext(HttpRequest()))
self.assertHTMLEqual(
rendered,
"""
<custom-template>
<header>Default header</header>
<main>Default main</main>
<footer>Default footer</footer>
</custom-template>
""",
)
@parametrize_context_behavior(["django", "isolated"]) @parametrize_context_behavior(["django", "isolated"])
def test_render_with_extends(self): def test_render_with_extends(self):
class SimpleComponent(Component): class SimpleComponent(Component):