From ec12a3bcb8e2cd0081cfdae55b35805bd5bb823e Mon Sep 17 00:00:00 2001 From: Juro Oravec Date: Mon, 15 Apr 2024 10:05:27 +0200 Subject: [PATCH] feat: capture root context --- src/django_components/component.py | 14 ++++++++++++++ src/django_components/slots.py | 1 + 2 files changed, 15 insertions(+) diff --git a/src/django_components/component.py b/src/django_components/component.py index 9dc2c7c8..2f7ba442 100644 --- a/src/django_components/component.py +++ b/src/django_components/component.py @@ -28,6 +28,7 @@ from django_components.slots import ( FillContent, SlotName, render_component_template_with_slots, + OUTER_CONTEXT_CONTEXT_KEY, DEFAULT_SLOT_KEY, ) from django_components.utils import search @@ -317,6 +318,12 @@ class ComponentNode(Node): resolved_component_name = self.name_fexp.resolve(context) component_cls: Type[Component] = registry.get(resolved_component_name) + # If this is the outer-/top-most component node, then save the outer context, + # so it can be used by nested Slots. + root_ctx_already_defined = OUTER_CONTEXT_CONTEXT_KEY in context + if not root_ctx_already_defined: + context.push({ OUTER_CONTEXT_CONTEXT_KEY: context.__copy__() }) + # Resolve FilterExpressions and Variables that were passed as args to the # component, then call component's context method # to get values to insert into the context @@ -344,8 +351,15 @@ class ComponentNode(Node): component_context: dict = component.get_context_data(*resolved_context_args, **resolved_context_kwargs) + # Prevent outer context from leaking into the template of the component if self.isolated_context: + # Even if contexts are isolated, we still need to pass down the + # original context so variables in slots can be rendered using + # the original context. + orig_ctx = context context = context.new() + context.push({ OUTER_CONTEXT_CONTEXT_KEY: orig_ctx }) + with context.update(component_context): rendered_component = component.render(context) diff --git a/src/django_components/slots.py b/src/django_components/slots.py index c5d4a3ad..069fa75a 100644 --- a/src/django_components/slots.py +++ b/src/django_components/slots.py @@ -20,6 +20,7 @@ from django.utils.safestring import SafeString, mark_safe FILLED_SLOTS_CONTENT_CONTEXT_KEY = "_DJANGO_COMPONENTS_FILLED_SLOTS" DEFAULT_SLOT_KEY = "_DJANGO_COMPONENTS_DEFAULT_SLOT" +OUTER_CONTEXT_CONTEXT_KEY = "_DJANGO_COMPONENTS_OUTER_CONTEXT" # Type aliases