Missing context variables and kwargs in component_block (#17)

* Fix issue with missing variables by binding template to context in Component.render method.
* Pass extra_context to Component.render()

Co-authored-by: rbeard0330 <@dul2k3BKW6m>
This commit is contained in:
rbeard0330 2020-12-14 12:25:36 -05:00 committed by GitHub
parent ab46ec7d69
commit be0a75e2a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 5 deletions

View file

@ -85,7 +85,9 @@ class Component(with_metaclass(MediaDefiningClass)):
else:
nodelist.append(node)
return nodelist.render(Context(context))
render_context = Context(context)
with render_context.bind_template(template.template):
return nodelist.render(render_context)
return template.render(context)

View file

@ -138,8 +138,8 @@ class ComponentNode(Node):
def render(self, context):
extra_context = {
key: filter_expression.resolve(context)
for key, filter_expression in self.extra_context.items()
key: context_item.resolve(context) if hasattr(context_item, 'resolve') else context_item
for key, context_item in self.extra_context.items()
}
context.update(extra_context)
@ -149,7 +149,7 @@ class ComponentNode(Node):
slots_filled = context.render_context[COMPONENT_CONTEXT_KEY][self.component]
return self.component.render(slots_filled=slots_filled, **context.flatten())
return self.component.render()
return self.component.render(**extra_context)
@register.tag("component_block")

View file

@ -0,0 +1,7 @@
{% load component_tags %}
<custom-template>
{{ missing_context_variable }}
<header>{% slot header %}Default header{% endslot %}</header>
<main>{% slot main %}Default main{% endslot %}</main>
<footer>{% slot footer %}Default footer{% endslot %}</footer>
</custom-template>

View file

@ -0,0 +1,2 @@
Provided variable: <strong>{{ variable }}</strong>
Default: <p>{{ default_param }}</p>

View file

@ -33,6 +33,11 @@ class SlottedComponent(component.Component):
return "slotted_template.html"
class SlottedComponentWithMissingVariable(component.Component):
def template(self, context):
return "slotted_template_with_missing_variable.html"
class SlottedComponentNoSlots(component.Component):
def template(self, context):
return "slotted_template_no_slots.html"
@ -46,6 +51,14 @@ class SlottedComponentWithContext(component.Component):
return "slotted_template.html"
class ComponentWithProvidedAndDefaultParameters(component.Component):
def context(self, variable, default_param="default text"):
return {"variable": variable, 'default_param': default_param}
def template(self, context):
return "template_with_provided_and_default_parameters.html"
class ComponentTemplateTagTest(SimpleTestCase):
def setUp(self):
# NOTE: component.registry is global, so need to clear before each test
@ -255,7 +268,7 @@ class ComponentSlottedTemplateTagTest(SimpleTestCase):
self.assertHTMLEqual(rendered, "<custom-template></custom-template>")
def test_slotted_template_without_slots_an_single_quotes(self):
def test_slotted_template_without_slots_and_single_quotes(self):
component.registry.register(name="test", component=SlottedComponentNoSlots)
template = Template(
"""
@ -266,3 +279,37 @@ class ComponentSlottedTemplateTagTest(SimpleTestCase):
rendered = template.render(Context({}))
self.assertHTMLEqual(rendered, "<custom-template></custom-template>")
class SlottedTemplateRegressionTests(SimpleTestCase):
def setUp(self):
# NOTE: component.registry is global, so need to clear before each test
component.registry.clear()
def test_slotted_template_that_uses_missing_variable(self):
component.registry.register(name="test", component=SlottedComponentWithMissingVariable)
template = Template(
"""
{% load component_tags %}
{% component_block 'test' %}{% endcomponent_block %}
"""
)
rendered = template.render(Context({}))
self.assertHTMLEqual(rendered, """
<custom-template>
<header>Default header</header>
<main>Default main</main>
<footer>Default footer</footer>
</custom-template>
""")
def test_component_block_accepts_provided_and_default_parameters(self):
component.registry.register(name="test", component=ComponentWithProvidedAndDefaultParameters)
template = Template(
'{% load component_tags %}{% component_block "test" variable="provided value" %}{% endcomponent_block %}'
)
rendered = template.render(Context({}))
self.assertHTMLEqual(rendered,
"Provided variable: <strong>provided value</strong>\nDefault: <p>default text</p>")