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:
Juro Oravec 2024-05-01 20:55:09 +02:00 committed by GitHub
parent 0f3491850b
commit 3fc90e4956
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 1394 additions and 838 deletions

View file

@ -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()