Component context and scope
By default, context variables are passed down the template as in regular Django - deeper scopes can access the variables from the outer scopes. So if you have several nested forloops, then inside the deep-most loop you can access variables defined by all previous loops.
With this in mind, the {% component %}
tag behaves similarly to {% include %}
tag - inside the component tag, you can access all variables that were defined outside of it.
And just like with {% include %}
, if you don't want a specific component template to have access to the parent context, add only
to the {% component %}
tag:
NOTE: {% csrf_token %}
tags need access to the top-level context, and they will not function properly if they are rendered in a component that is called with the only
modifier.
If you find yourself using the only
modifier often, you can set the context_behavior option to "isolated"
, which automatically applies the only
modifier. This is useful if you want to make sure that components don't accidentally access the outer context.
Components can also access the outer context in their context methods like get_context_data
by accessing the property self.outer_context
.
Example of Accessing Outer Context¤
Assuming that the rendering context has variables such as date
, you can use self.outer_context
to access them from within get_context_data
. Here's how you might implement it:
class Calender(Component):
...
def get_context_data(self):
outer_field = self.outer_context["date"]
return {
"date": outer_fields,
}
However, as a best practice, it’s recommended not to rely on accessing the outer context directly through self.outer_context
. Instead, explicitly pass the variables to the component. For instance, continue passing the variables in the component tag as shown in the previous examples.
Context behavior¤
django_components supports both Django and Vue-like behavior when it comes to passing data to and through components. This can be configured in context_behavior.
This has two modes:
-
"django"
The default Django template behavior.
Inside the
{% fill %}
tag, the context variables you can access are a union of:- All the variables that were OUTSIDE the fill tag, including any\
{% with %}
tags. - Any loops (
{% for ... %}
) that the{% fill %}
tag is part of. - Data returned from
Component.get_context_data()
of the component that owns the fill tag.
- All the variables that were OUTSIDE the fill tag, including any\
-
"isolated"
Similar behavior to Vue or React, this is useful if you want to make sure that components don't accidentally access variables defined outside of the component.
Inside the
{% fill %}
tag, you can ONLY access variables from 2 places:- Any loops (
{% for ... %}
) that the{% fill %}
tag is part of. Component.get_context_data()
of the component which defined the template (AKA the "root" component).
- Any loops (
Warning
Notice that the component whose get_context_data()
we use inside {% fill %}
is NOT the same across the two modes!
Consider this example:
class Outer(Component):
template = \"\"\"
<div>
{% component "inner" %}
{% fill "content" %}
{{ my_var }}
{% endfill %}
{% endcomponent %}
</div>
\"\"\"
-
"django"
-my_var
has access to data fromget_context_data()
of bothInner
andOuter
. If there are variables defined in both, thenInner
overshadowsOuter
. -
"isolated"
-my_var
has access to data fromget_context_data()
of ONLYOuter
.
Example "django"¤
Given this template:
@register("root_comp")
class RootComp(Component):
template = """
{% with cheese="feta" %}
{% component 'my_comp' %}
{{ my_var }} # my_var
{{ cheese }} # cheese
{% endcomponent %}
{% endwith %}
"""
def get_context_data(self):
return { "my_var": 123 }
Then if get_context_data()
of the component "my_comp"
returns following data:
Then the template will be rendered as:
Because "my_comp"
overshadows the outer variable "my_var"
, so {{ my_var }}
equals 456
.
And variable "cheese"
equals feta
, because the fill CAN access all the data defined in the outer layers, like the {% with %}
tag.
Example "isolated"¤
Given this template:
class RootComp(Component):
template = """
{% with cheese="feta" %}
{% component 'my_comp' %}
{{ my_var }} # my_var
{{ cheese }} # cheese
{% endcomponent %}
{% endwith %}
"""
def get_context_data(self):
return { "my_var": 123 }
Then if get_context_data()
of the component "my_comp"
returns following data:
Then the template will be rendered as:
Because variables "my_var"
and "cheese"
are searched only inside RootComponent.get_context_data()
. But since "cheese"
is not defined there, it's empty.
Info
Notice that the variables defined with the {% with %}
tag are ignored inside the {% fill %}
tag with the "isolated"
mode.