You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,10 @@
2
2
3
3
## [Unreleased]
4
4
5
+
### Added
6
+
7
+
- Added support for 'context modifiers' - A way to modify template contexts with Python [#141](https://github.com/torchbox/django-pattern-library/pull/141)
Copy file name to clipboardExpand all lines: docs/guides/defining-template-context.md
+149-2Lines changed: 149 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ Let's assume you have the following template:
40
40
{% endif %}
41
41
```
42
42
43
-
You might define a `yaml` file similar to this to provide fake data:
43
+
You might define a YAML file similar to this to provide fake data:
44
44
45
45
```yaml
46
46
name: My example pattern
@@ -56,4 +56,151 @@ context:
56
56
link: /page2
57
57
```
58
58
59
-
You can define a list or a dict or anything that [`PyYAML`](http://pyyaml.org/wiki/PyYAMLDocumentation) allows you to create in `yaml` format without creating a custom objects.
59
+
You can define a list or a dict or anything that [`PyYAML`](http://pyyaml.org/wiki/PyYAMLDocumentation) allows you to create in YAML format without creating a custom objects.
60
+
61
+
62
+
## Modifying template contexts with Python
63
+
64
+
While most objects can be faked with YAML, Django has a few common constructs that are difficult to replicate. For example: `Form`and `Paginator` instances. To help with this, django-pattern-library allows you to register any number of 'context modifiers'. Context modifiers are simply Python functions that accept the `context` dictionary generated from the YAML file, and can make additions or updates to it as necessary. For convenience, they also receive the current `HttpRequest` as `request`.
65
+
66
+
Context modifiers can easily be registered using the `register_context_modifier` decorator. Here is a simple example:
67
+
68
+
```python
69
+
70
+
# myproject/core/pattern_contexts.py
71
+
72
+
from pattern_library import register_context_modifier
73
+
from myproject.core.forms import SearchForm, SignupForm
74
+
75
+
@register_context_modifier
76
+
def add_common_forms(context, request):
77
+
if 'search_form' not in context:
78
+
context["search_form"] = SearchForm()
79
+
if 'signup_form' not in context:
80
+
context["signup_form"] = SignupForm()
81
+
82
+
```
83
+
84
+
Context modifiers are also great for reducing the amount of template tag patching that is needed. The following examples are from a Wagtail project:
85
+
86
+
```python
87
+
88
+
# myproject/core/pattern_contexts.py
89
+
90
+
from django.core.paginator import Paginator
91
+
from wagtail.images import get_image_model
92
+
from pattern_library import register_context_modifier
93
+
94
+
95
+
@register_context_modifier
96
+
def add_page_images(context, request):
97
+
"""
98
+
Replace some common 'image' field values on pages with real `Image`
99
+
instances, so that the {% image %} template tag will work.
### Registering a context modifier for a specific template
137
+
138
+
By default, context modifiers are applied to all pattern library templates. If you only wish for a context modifier to be applied to a specific pattern, you can use the ``template`` parameter to indicate this. For example:
139
+
140
+
```python
141
+
142
+
# myproject/accounts/pattern_contexts.py
143
+
144
+
from pattern_library import register_context_modifier
Adds a bound form with invalid data to 'form_invalid.html'
160
+
"""
161
+
context["form"] = SubscribeForm(data={
162
+
"email": 'invalid-email',
163
+
"name": ''
164
+
})
165
+
```
166
+
167
+
### Controlling the order in which context modifiers are applied
168
+
169
+
By default, context modifiers are applied in the order they were registered (which can be difficult to predict accross multiple apps), with generic context modifiers being applied first, followed by template-specific ones. If you need to control the order in which a series of context modifiers are applied, you can use the `order` parameter to do this.
170
+
171
+
In the following example, a generic context modifier is registered with an `order` value of `1`, while others recieve the default value of `0`. Because `1` is higher than `0`, the generic context modifier will be applied **after** the others.
172
+
173
+
```python
174
+
175
+
# myproject/sums/pattern_contexts.py
176
+
177
+
178
+
from pattern_library import register_context_modifier
0 commit comments