Skip to content

Commit 2d282e4

Browse files
committed
WIP Jinja support.
1 parent 6f79c4c commit 2d282e4

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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+
30+
def __init__(self, environment):
31+
super().__init__(environment)
32+
#
33+
# All we need is to add global "component" to the environment.
34+
#
35+
environment.globals["component"] = self._jinja_component
36+
37+
@pass_context
38+
def _jinja_component(self, __context: Context, dotted_path: str, *args: t.Any, host: str | None = None,
39+
prerender: str = str(config.REACTPY_PRERENDER), **kwargs: t.Any) -> t.Union[t.Any, Undefined]:
40+
"""
41+
This method is used to embed an existing ReactPy component into your
42+
Jinja2 template.
43+
44+
Args:
45+
dotted_path: String of the fully qualified name of a component.
46+
*args: The positional arguments to provide to the component.
47+
48+
Keyword Args:
49+
class: The HTML class to apply to the top-level component div.
50+
key: Force the component's root node to use a specific key value. \
51+
Using key within a template tag is effectively useless.
52+
host: The host to use for the ReactPy connections. If set to `None`, \
53+
the host will be automatically configured. \
54+
Example values include: `localhost:8000`, `example.com`, `example.com/subdir`
55+
prerender: Configures whether to pre-render this component, which \
56+
enables SEO compatibility and reduces perceived latency.
57+
**kwargs: The keyword arguments to provide to the component.
58+
59+
Returns:
60+
Whatever the components returns.
61+
"""
62+
djt_context = RequestContext(__context.parent['request'], autoescape=__context.eval_ctx.autoescape)
63+
context = djt_component(djt_context, dotted_path, *args, host=host, prerender=prerender, **kwargs)
64+
#
65+
# TODO: can this be usefully cached?
66+
#
67+
result = loader.render_to_string(self.DJT_TEMPLATE, context, __context.parent['request'])
68+
return result

0 commit comments

Comments
 (0)