mirror of
https://github.com/django-components/django-components.git
synced 2025-08-10 09:17:59 +00:00
feat: merge context settings, replace if_filled tag with var
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
0f3491850b
commit
3fc90e4956
17 changed files with 1394 additions and 838 deletions
|
@ -5,27 +5,27 @@ from django.conf import settings
|
|||
|
||||
|
||||
class ContextBehavior(str, Enum):
|
||||
GLOBAL = "global"
|
||||
ISOLATED = "isolated"
|
||||
|
||||
|
||||
class SlotContextBehavior(str, Enum):
|
||||
ALLOW_OVERRIDE = "allow_override"
|
||||
DJANGO = "django"
|
||||
"""
|
||||
Components CAN override the slot context variables passed from the outer scopes.
|
||||
Contexts of deeper components take precedence over shallower ones.
|
||||
With this setting, component fills behave as usual Django tags.
|
||||
That is, they enrich the context, and pass it along.
|
||||
|
||||
1. Component fills use the context of the component they are within.
|
||||
2. Variables from `get_context_data` are available to the component fill.
|
||||
|
||||
Example:
|
||||
|
||||
Given this template
|
||||
|
||||
```txt
|
||||
{% component 'my_comp' %}
|
||||
{{ my_var }}
|
||||
{% endcomponent %}
|
||||
```django
|
||||
{% with cheese="feta" %}
|
||||
{% component 'my_comp' %}
|
||||
{{ my_var }} # my_var
|
||||
{{ cheese }} # cheese
|
||||
{% endcomponent %}
|
||||
{% endwith %}
|
||||
```
|
||||
|
||||
and this context passed to the render function (AKA root context)
|
||||
and this context returned from the `get_context_data()` method
|
||||
```py
|
||||
{ "my_var": 123 }
|
||||
```
|
||||
|
@ -35,59 +35,37 @@ class SlotContextBehavior(str, Enum):
|
|||
{ "my_var": 456 }
|
||||
```
|
||||
|
||||
Then since "my_comp" overrides the varialbe "my_var", so `{{ my_var }}` will equal `456`.
|
||||
"""
|
||||
|
||||
PREFER_ROOT = "prefer_root"
|
||||
"""
|
||||
This is the same as "allow_override", except any variables defined in the root context
|
||||
take precedence over anything else.
|
||||
|
||||
So if a variable is found in the root context, then root context is used.
|
||||
Otherwise, the context of the component where the slot fill is located is used.
|
||||
|
||||
Example:
|
||||
|
||||
Given this template
|
||||
|
||||
```txt
|
||||
{% component 'my_comp' %}
|
||||
{{ my_var_one }}
|
||||
{{ my_var_two }}
|
||||
{% endcomponent %}
|
||||
Then this will render:
|
||||
```django
|
||||
456 # my_var
|
||||
feta # cheese
|
||||
```
|
||||
|
||||
and this context passed to the render function (AKA root context)
|
||||
```py
|
||||
{ "my_var_one": 123 }
|
||||
```
|
||||
Because "my_comp" overrides the variable "my_var",
|
||||
so `{{ my_var }}` equals `456`.
|
||||
|
||||
Then if component "my_comp" defines context
|
||||
```py
|
||||
{ "my_var": 456, "my_var_two": "abc" }
|
||||
```
|
||||
|
||||
Then the rendered `{{ my_var_one }}` will equal to `123`, and `{{ my_var_two }}`
|
||||
will equal to "abc".
|
||||
And variable "cheese" will equal `feta`, because the fill CAN access
|
||||
the current context.
|
||||
"""
|
||||
|
||||
ISOLATED = "isolated"
|
||||
"""
|
||||
This setting makes the slots behave similar to Vue or React, where
|
||||
the slot uses EXCLUSIVELY the root context, and nested components CANNOT
|
||||
override context variables inside the slots.
|
||||
This setting makes the component fills behave similar to Vue or React, where
|
||||
the fills use EXCLUSIVELY the context variables defined in `get_context_data`.
|
||||
|
||||
Example:
|
||||
|
||||
Given this template
|
||||
|
||||
```txt
|
||||
{% component 'my_comp' %}
|
||||
{{ my_var }}
|
||||
{% endcomponent %}
|
||||
```django
|
||||
{% with cheese="feta" %}
|
||||
{% component 'my_comp' %}
|
||||
{{ my_var }} # my_var
|
||||
{{ cheese }} # cheese
|
||||
{% endcomponent %}
|
||||
{% endwith %}
|
||||
```
|
||||
|
||||
and this context passed to the render function (AKA root context)
|
||||
and this context returned from the `get_context_data()` method
|
||||
```py
|
||||
{ "my_var": 123 }
|
||||
```
|
||||
|
@ -97,7 +75,14 @@ class SlotContextBehavior(str, Enum):
|
|||
{ "my_var": 456 }
|
||||
```
|
||||
|
||||
Then the rendered `{{ my_var }}` will equal `123`.
|
||||
Then this will render:
|
||||
```django
|
||||
123 # my_var
|
||||
# cheese
|
||||
```
|
||||
|
||||
Because both variables "my_var" and "cheese" are taken from the root context.
|
||||
Since "cheese" is not defined in root context, it's empty.
|
||||
"""
|
||||
|
||||
|
||||
|
@ -120,7 +105,7 @@ class AppSettings:
|
|||
|
||||
@property
|
||||
def CONTEXT_BEHAVIOR(self) -> ContextBehavior:
|
||||
raw_value = self.settings.get("context_behavior", ContextBehavior.GLOBAL.value)
|
||||
raw_value = self.settings.get("context_behavior", ContextBehavior.ISOLATED.value)
|
||||
return self._validate_context_behavior(raw_value)
|
||||
|
||||
def _validate_context_behavior(self, raw_value: ContextBehavior) -> ContextBehavior:
|
||||
|
@ -130,17 +115,5 @@ class AppSettings:
|
|||
valid_values = [behavior.value for behavior in ContextBehavior]
|
||||
raise ValueError(f"Invalid context behavior: {raw_value}. Valid options are {valid_values}")
|
||||
|
||||
@property
|
||||
def SLOT_CONTEXT_BEHAVIOR(self) -> SlotContextBehavior:
|
||||
raw_value = self.settings.get("slot_context_behavior", SlotContextBehavior.PREFER_ROOT.value)
|
||||
return self._validate_slot_context_behavior(raw_value)
|
||||
|
||||
def _validate_slot_context_behavior(self, raw_value: SlotContextBehavior) -> SlotContextBehavior:
|
||||
try:
|
||||
return SlotContextBehavior(raw_value)
|
||||
except ValueError:
|
||||
valid_values = [behavior.value for behavior in SlotContextBehavior]
|
||||
raise ValueError(f"Invalid slot context behavior: {raw_value}. Valid options are {valid_values}")
|
||||
|
||||
|
||||
app_settings = AppSettings()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue