Skip to content

Commit 7e97489

Browse files
committed
WIP Jinja support.
1 parent 6f79c4c commit 7e97489

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Copyright © 2023 Innovatie Ltd. All rights reserved.
2+
"""
3+
Jinja support.
4+
"""
5+
import typing as t
6+
7+
from django.template import RequestContext, loader
8+
from jinja2 import pass_context
9+
from jinja2.ext import Extension
10+
from jinja2.runtime import Context, Undefined
11+
12+
from .reactpy import component as djt_component
13+
from .. import config
14+
15+
16+
class ReactPyExtension(Extension):
17+
"""
18+
Jinja has more expressive power than core Django's templates, and can
19+
directly handle expansions such as:
20+
21+
{{ component(*args, **kwargs) }}
22+
"""
23+
DJT_TEMPLATE = 'reactpy/component.html'
24+
#
25+
# Therefore, there is no new tag to parse().
26+
#
27+
tags = {}
28+
29+
def __init__(self, environment):
30+
super().__init__(environment)
31+
#
32+
# All we need is to add global "component" to the environment.
33+
#
34+
environment.globals["component"] = self._jinja_component
35+
36+
@pass_context
37+
def _jinja_component(self, __context: Context, dotted_path: str, *args: t.Any, host: str | None = None,
38+
prerender: str = str(config.REACTPY_PRERENDER), **kwargs: t.Any) -> t.Union[t.Any, Undefined]:
39+
"""
40+
This method is used to embed an existing ReactPy component into your
41+
Jinja2 template.
42+
43+
Args:
44+
dotted_path: String of the fully qualified name of a component.
45+
*args: The positional arguments to provide to the component.
46+
47+
Keyword Args:
48+
class: The HTML class to apply to the top-level component div.
49+
key: Force the component's root node to use a specific key value. \
50+
Using key within a template tag is effectively useless.
51+
host: The host to use for the ReactPy connections. If set to `None`, \
52+
the host will be automatically configured. \
53+
Example values include: `localhost:8000`, `example.com`, `example.com/subdir`
54+
prerender: Configures whether to pre-render this component, which \
55+
enables SEO compatibility and reduces perceived latency.
56+
**kwargs: The keyword arguments to provide to the component.
57+
58+
Returns:
59+
Whatever the components returns.
60+
"""
61+
djt_context = RequestContext(__context.parent['request'], autoescape=__context.eval_ctx.autoescape)
62+
context = djt_component(djt_context, dotted_path, *args, host=host, prerender=prerender, **kwargs)
63+
#
64+
# TODO: can this be usefully cached?
65+
#
66+
result = loader.render_to_string(self.DJT_TEMPLATE, context, __context.parent['request'])
67+
return result

0 commit comments

Comments
 (0)