fastlifeweb 0.3.1__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastlife/configurator/registry.py +2 -2
- fastlife/configurator/settings.py +3 -0
- fastlife/templates/A.jinja +30 -4
- fastlife/templates/Button.jinja +31 -17
- fastlife/templates/Checkbox.jinja +20 -2
- fastlife/templates/CsrfToken.jinja +0 -1
- fastlife/templates/Form.jinja +9 -3
- fastlife/templates/H1.jinja +15 -4
- fastlife/templates/H2.jinja +15 -4
- fastlife/templates/H3.jinja +14 -0
- fastlife/templates/H4.jinja +14 -0
- fastlife/templates/H5.jinja +14 -0
- fastlife/templates/H6.jinja +14 -0
- fastlife/templates/Input.jinja +29 -6
- fastlife/templates/Label.jinja +10 -2
- fastlife/templates/Option.jinja +4 -2
- fastlife/templates/P.jinja +9 -0
- fastlife/templates/Radio.jinja +29 -7
- fastlife/templates/Select.jinja +25 -6
- fastlife/templates/pydantic_form/Boolean.jinja +1 -1
- fastlife/templates/pydantic_form/Dropdown.jinja +4 -6
- fastlife/templates/pydantic_form/Hint.jinja +4 -0
- fastlife/templates/pydantic_form/Model.jinja +1 -1
- fastlife/templates/pydantic_form/Sequence.jinja +3 -3
- fastlife/templates/pydantic_form/Text.jinja +1 -3
- fastlife/templates/pydantic_form/Union.jinja +5 -5
- fastlife/templating/__init__.py +2 -2
- fastlife/templating/binding.py +4 -22
- fastlife/templating/renderer/__init__.py +5 -2
- fastlife/templating/renderer/abstract.py +7 -5
- fastlife/templating/renderer/jinjax.py +51 -23
- fastlife/templating/renderer/widgets/base.py +12 -2
- fastlife/templating/renderer/widgets/boolean.py +4 -3
- fastlife/templating/renderer/widgets/dropdown.py +7 -6
- fastlife/templating/renderer/widgets/factory.py +38 -21
- fastlife/templating/renderer/widgets/hidden.py +2 -3
- fastlife/templating/renderer/widgets/model.py +7 -6
- fastlife/templating/renderer/widgets/sequence.py +8 -9
- fastlife/templating/renderer/widgets/text.py +9 -5
- fastlife/templating/renderer/widgets/union.py +7 -6
- fastlife/testing/testclient.py +116 -55
- fastlife/views/pydantic_form.py +5 -2
- {fastlifeweb-0.3.1.dist-info → fastlifeweb-0.4.0.dist-info}/METADATA +5 -4
- fastlifeweb-0.4.0.dist-info/RECORD +69 -0
- fastlifeweb-0.3.1.dist-info/RECORD +0 -63
- {fastlifeweb-0.3.1.dist-info → fastlifeweb-0.4.0.dist-info}/LICENSE +0 -0
- {fastlifeweb-0.3.1.dist-info → fastlifeweb-0.4.0.dist-info}/WHEEL +0 -0
@@ -7,7 +7,7 @@ from fastlife.shared_utils.resolver import resolve
|
|
7
7
|
|
8
8
|
if TYPE_CHECKING:
|
9
9
|
from fastlife.templating.renderer import ( # coverage: ignore
|
10
|
-
|
10
|
+
AbstractTemplateRendererFactory, # coverage: ignore
|
11
11
|
) # coverage: ignore
|
12
12
|
|
13
13
|
from .settings import Settings
|
@@ -15,7 +15,7 @@ from .settings import Settings
|
|
15
15
|
|
16
16
|
class AppRegistry:
|
17
17
|
settings: Settings
|
18
|
-
renderer: "
|
18
|
+
renderer: "AbstractTemplateRendererFactory"
|
19
19
|
check_permission: CheckPermission
|
20
20
|
|
21
21
|
def __init__(self, settings: Settings) -> None:
|
@@ -17,6 +17,9 @@ class Settings(BaseSettings):
|
|
17
17
|
form_data_model_prefix: str = Field(default="payload")
|
18
18
|
csrf_token_name: str = Field(default="csrf_token")
|
19
19
|
|
20
|
+
jinjax_use_cache: bool = Field(default=True)
|
21
|
+
jinjax_auto_reload: bool = Field(default=False)
|
22
|
+
|
20
23
|
session_secret_key: str = Field(default="")
|
21
24
|
session_cookie_name: str = Field(default="flsess")
|
22
25
|
session_cookie_domain: str = Field(default="")
|
fastlife/templates/A.jinja
CHANGED
@@ -1,5 +1,31 @@
|
|
1
|
-
{# def
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
{# def
|
2
|
+
href,
|
3
|
+
disable_htmx=false,
|
4
|
+
hx_target="#maincontent",
|
5
|
+
hx_select=None,
|
6
|
+
hx_swap="innerHTML show:body:top",
|
7
|
+
hx_push_url=true,
|
8
|
+
class_="""
|
9
|
+
bg-neutral-200
|
10
|
+
px-5
|
11
|
+
py-2.5
|
12
|
+
rounded-lg
|
13
|
+
text-center
|
14
|
+
text-neutral-900
|
15
|
+
text-sm
|
16
|
+
font-medium
|
17
|
+
focus:outline-none
|
18
|
+
focus:ring-4
|
19
|
+
focus:ring-primary-300
|
20
|
+
hover:bg-neutral-50
|
21
|
+
dark:bg-neutral-400
|
22
|
+
dark:focus:ring-neutral-100
|
23
|
+
dark:hover:bg-neutral-300
|
24
|
+
"""
|
25
|
+
#}
|
26
|
+
|
27
|
+
<a href="{{href}}" {% if not disable_htmx %} hx-get="{{href}}" hx-target="{{hx_target}}" hx-swap="{{hx_swap}}" {% if
|
28
|
+
hx_push_url %} hx-push-url="true" {%- endif %}{% if hx_select %} hx-select="{{hx_select}}" {%- endif %}{%- endif
|
29
|
+
%}class="{{attrs.class or class_}}">
|
30
|
+
{{- content -}}
|
5
31
|
</a>
|
fastlife/templates/Button.jinja
CHANGED
@@ -3,25 +3,39 @@ type="submit",
|
|
3
3
|
id="",
|
4
4
|
name="action",
|
5
5
|
value="submit",
|
6
|
+
hidden=false,
|
7
|
+
aria_label="",
|
6
8
|
onclick="",
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
hx_target="",
|
10
|
+
hx_swap="",
|
11
|
+
hx_get="",
|
12
|
+
hx_select="",
|
13
|
+
hx_after_request="",
|
14
|
+
hx_vals="",
|
13
15
|
full_width=false,
|
14
|
-
|
15
|
-
|
16
|
+
class_="""
|
17
|
+
bg-primary-600
|
18
|
+
font-medium
|
19
|
+
px-5
|
20
|
+
py-2.5
|
21
|
+
rounded-lg
|
22
|
+
text-center
|
23
|
+
text-sm
|
24
|
+
text-white
|
25
|
+
hover:bg-primary-700
|
26
|
+
focus:outline-none
|
27
|
+
focus:ring-4
|
28
|
+
focus:ring-primary-300
|
29
|
+
dark:bg-primary-600
|
30
|
+
dark:focus:ring-primary-800
|
31
|
+
dark:hover:bg-primary-700
|
32
|
+
"""
|
16
33
|
#}
|
17
|
-
{% set css = "text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300
|
18
|
-
font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700
|
19
|
-
dark:focus:ring-primary-800" %}
|
20
34
|
<button type="{{type}}" {%if id %}id="{{id}}" {%endif%} name="{{name}}" value="{{value}}" {% if
|
21
|
-
|
22
|
-
%}hx-select="{{
|
23
|
-
endif %}{% if
|
24
|
-
%}hx-vals='{{
|
25
|
-
class="{% if full_width %}w-full {% endif %}{{
|
26
|
-
{{ content}}
|
35
|
+
hx_target%}hx-target="{{hx_target}}" {% endif %} {% if hx_swap %}hx-swap="{{hx_swap}}" {% endif %} {% if hx_select
|
36
|
+
%}hx-select="{{hx_select}}" {% endif %} {% if hx_get %}hx-get="{{hx_get}}" {% endif %} {% if onclick %}onclick="{{onclick}}" {%
|
37
|
+
endif %}{% if hx_after_request %}hx-on::after-request="{{hx_after_request}}" {% endif %} {% if hx_vals
|
38
|
+
%}hx-vals='{{hx_vals|safe}}' {% endif %} {% if aria_label %}aria-label="{{aria_label}}" {% endif %}
|
39
|
+
class="{% if full_width %}w-full {% endif %}{{attrs.class or class_}}" {% if hidden %}hidden{% endif %}>
|
40
|
+
{{- content -}}
|
27
41
|
</button>
|
@@ -1,2 +1,20 @@
|
|
1
|
-
{# def
|
2
|
-
|
1
|
+
{# def
|
2
|
+
name,
|
3
|
+
value,
|
4
|
+
id,
|
5
|
+
class_="""
|
6
|
+
bg-neutral-100
|
7
|
+
border-neutral-300
|
8
|
+
h-4
|
9
|
+
rounded
|
10
|
+
text-primary-600
|
11
|
+
w-4
|
12
|
+
dark:bg-neutral-700
|
13
|
+
dark:border-neutral-600
|
14
|
+
dark:focus:ring-primary-600
|
15
|
+
dark:ring-offset-neutral-800
|
16
|
+
focus:ring-2
|
17
|
+
focus:ring-primary-500
|
18
|
+
"""
|
19
|
+
#}
|
20
|
+
<input name="{{name}}" {% if value%}checked{% endif %} type="checkbox" id="{{id}}" class="{{attrs.class or class_}}" />
|
fastlife/templates/Form.jinja
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
-
{# def
|
2
|
-
|
3
|
-
|
1
|
+
{# def
|
2
|
+
method="",
|
3
|
+
action=None,
|
4
|
+
hx_post=None,
|
5
|
+
class_="space-y-4 md:space-y-6"
|
6
|
+
#}
|
7
|
+
<form class="{{attrs.class or class_}}" {% if hx_post is not none %}hx-post="{{hx_post}}" {% endif %}{% if action is not
|
8
|
+
none %}action="{{action}}" {% endif %}{% if method %}method="{{method}}" {% endif %}>
|
9
|
+
<CsrfToken />
|
4
10
|
{{ content }}
|
5
11
|
</form>
|
fastlife/templates/H1.jinja
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
{# def
|
2
|
+
class_="""
|
3
|
+
block
|
4
|
+
font-bold
|
5
|
+
font-sans
|
6
|
+
leading-tight
|
7
|
+
pb-4
|
8
|
+
text-5xl
|
9
|
+
text-neutral-900
|
10
|
+
tracking-tight
|
11
|
+
dark:text-white
|
12
|
+
md:text-4xl
|
13
|
+
"""
|
14
|
+
#}
|
15
|
+
<h1 class="{{attrs.class or class_}}">{{ content }}</h1>
|
fastlife/templates/H2.jinja
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
{# def
|
2
|
+
class_="""
|
3
|
+
block
|
4
|
+
font-bold
|
5
|
+
font-sans
|
6
|
+
leading-tight
|
7
|
+
pb-4
|
8
|
+
text-4xl
|
9
|
+
text-neutral-900
|
10
|
+
tracking-tight
|
11
|
+
dark:text-white
|
12
|
+
md:text-4xl
|
13
|
+
"""
|
14
|
+
#}
|
15
|
+
<h2 class="{{attrs.class or class_}}">{{ content }}</h2>
|
fastlife/templates/Input.jinja
CHANGED
@@ -1,8 +1,31 @@
|
|
1
|
-
{# def
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
{# def
|
2
|
+
name,
|
3
|
+
value="",
|
4
|
+
type="text",
|
5
|
+
id="",
|
6
|
+
aria_label="",
|
7
|
+
placeholder="",
|
8
|
+
class_="""
|
9
|
+
bg-neutral-50
|
10
|
+
block
|
11
|
+
border
|
12
|
+
border-neutral-300
|
13
|
+
p-2.5
|
14
|
+
rounded-lg
|
15
|
+
text-base
|
16
|
+
text-neutral-900
|
17
|
+
w-full
|
18
|
+
dark:bg-neutral-700
|
19
|
+
dark:border-neutral-600
|
20
|
+
dark:focus:border-primary-500
|
21
|
+
dark:focus:ring-primary-500
|
22
|
+
dark:placeholder-neutral-400
|
23
|
+
dark:text-white
|
24
|
+
focus:border-primary-500
|
25
|
+
focus:ring-primary-500
|
26
|
+
"""
|
27
|
+
#}
|
5
28
|
|
6
|
-
<input name="{{name}}" value="{{value}}" type="{{
|
29
|
+
<input name="{{name}}" value="{{value}}" type="{{type}}" {% if id %}id="{{id}}" {% endif %}{% if aria_label
|
7
30
|
%}aria-label="{{aria_label}}" {% endif %} {% if placeholder %}placeholder="{{placeholder}}" {% endif %}
|
8
|
-
class="{{
|
31
|
+
class="{{attrs.class or class_}}" />
|
fastlife/templates/Label.jinja
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
-
{
|
1
|
+
{#def
|
2
|
+
class_="""
|
3
|
+
block
|
4
|
+
font-bold
|
5
|
+
mb-2
|
6
|
+
text-base
|
7
|
+
text-neutral-900
|
8
|
+
dark:text-white
|
9
|
+
""" #}
|
2
10
|
|
3
|
-
<label for="{{attrs.for}}" class="{{
|
11
|
+
<label for="{{attrs.for}}" class="{{attrs.class or class_}}">{{content}}</label>
|
fastlife/templates/Option.jinja
CHANGED
fastlife/templates/Radio.jinja
CHANGED
@@ -1,8 +1,30 @@
|
|
1
|
-
{# def
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
{# def
|
2
|
+
label,
|
3
|
+
name,
|
4
|
+
id,
|
5
|
+
value,
|
6
|
+
checked=false,
|
7
|
+
disabled=false,
|
8
|
+
onclick="",
|
9
|
+
class_="""
|
10
|
+
bg-neutral-100
|
11
|
+
border-neutral-300
|
12
|
+
w-4
|
13
|
+
h-4
|
14
|
+
text-primary-600
|
15
|
+
focus:ring-2
|
16
|
+
focus:ring-primary-500
|
17
|
+
dark:bg-neutral-700
|
18
|
+
dark:border-neutral-600
|
19
|
+
dark:focus:ring-primary-600
|
20
|
+
dark:ring-offset-neutral-800
|
21
|
+
""",
|
22
|
+
label_class="ms-2 text-sm font-medium text-neutral-900 dark:text-neutral-300",
|
23
|
+
div_class="flex items-center mb-4"
|
24
|
+
#}
|
25
|
+
<div class="{{div_class}}">
|
26
|
+
<input type="radio" name="{{name}}" id="{{id}}" value="{{value}}" {% if checked %}checked{% endif %}
|
27
|
+
class="{{attrs.class or class_}}" {% if onclick %}onclick="{{onclick}}" {% endif %} {%if
|
28
|
+
disabled%}disabled{%endif%}>
|
29
|
+
<Label for={id} class={label_class}>{{label}}</Label>
|
8
30
|
</div>
|
fastlife/templates/Select.jinja
CHANGED
@@ -1,8 +1,27 @@
|
|
1
|
-
{# def
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
{# def
|
2
|
+
name,
|
3
|
+
id,
|
4
|
+
class_="""
|
5
|
+
bg-neutral-50
|
6
|
+
block
|
7
|
+
border
|
8
|
+
border-neutral-300
|
9
|
+
p-2.5
|
10
|
+
rounded-lg
|
11
|
+
text-base
|
12
|
+
text-neutral-900
|
13
|
+
w-full
|
14
|
+
focus:border-primary-500
|
15
|
+
focus:ring-primary-500
|
16
|
+
dark:bg-neutral-700
|
17
|
+
dark:border-neutral-600
|
18
|
+
dark:focus:border-primary-500
|
19
|
+
dark:focus:ring-primary-500
|
20
|
+
dark:placeholder-neutral-400
|
21
|
+
dark:text-white
|
22
|
+
"""
|
23
|
+
#}
|
5
24
|
|
6
|
-
<select name="{{name}}" id="{{id}}" class="{{
|
7
|
-
{{content}}
|
25
|
+
<select name="{{name}}" id="{{id}}" class="{{attrs.class or class_}}">
|
26
|
+
{{- content -}}
|
8
27
|
</select>
|
@@ -2,6 +2,6 @@
|
|
2
2
|
<pydantic_form.Widget widget={widget} removable={widget.removable}>
|
3
3
|
<div class="pt-4">
|
4
4
|
<Label for={widget.id}>{{widget.title}}</Label>
|
5
|
-
<Checkbox name={widget.name}
|
5
|
+
<Checkbox name={widget.name} type="checkbox" id={widget.id} {% if widget.value %}checked{% endif %} />
|
6
6
|
</div>
|
7
7
|
</pydantic_form.Widget>
|
@@ -5,13 +5,11 @@
|
|
5
5
|
<Label for={widget.id}>{{widget.title}}</Label>
|
6
6
|
<Select name={widget.name} id={widget.id}>
|
7
7
|
{%- for opt in widget.options -%}
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
<Option value={opt.value} id={widget.id + "-" + opt.value} selected={widget.value==opt.value}>
|
9
|
+
{{ opt.text }}
|
10
|
+
</Option>
|
11
11
|
{%- endfor -%}
|
12
12
|
</Select>
|
13
|
-
{
|
14
|
-
<span class="mt-2 text-sm text-neutral-500 dark:text-neutral-400">{{widget.help_text}}</span>
|
15
|
-
{%- endif %}
|
13
|
+
<pydantic_form.Hint text={widget.hint} />
|
16
14
|
</div>
|
17
15
|
</pydantic_form.Widget>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<div id="{{widget.id}}" class="m-4">
|
5
5
|
<details open>
|
6
6
|
<summary class="justify-between items-center font-medium cursor-pointer">
|
7
|
-
<
|
7
|
+
<H3>{{widget.title}}</H3>
|
8
8
|
</summary>
|
9
9
|
<div>
|
10
10
|
{% for child in children_widget %}
|
@@ -3,12 +3,12 @@
|
|
3
3
|
<pydantic_form.Widget widget={widget} removable={widget.removable}>
|
4
4
|
<details id="{{widget.id}}" open>
|
5
5
|
<summary class="justify-between items-center font-medium cursor-pointer">
|
6
|
-
<
|
6
|
+
<H3>{{widget.title}}</H3>
|
7
7
|
</summary>
|
8
8
|
<div>
|
9
9
|
{% set fnGetName = "get" + widget.id.replace("-", "_") %}
|
10
10
|
<script>
|
11
|
-
function {{fnGetName}}() {
|
11
|
+
function {{ fnGetName }} () {
|
12
12
|
const el = document.getElementById("{{widget.id}}-content");
|
13
13
|
const len = el.dataset.length;
|
14
14
|
el.dataset.length = parseInt(len) + 1;
|
@@ -28,7 +28,7 @@
|
|
28
28
|
{% set container_id = "#" + widget.id + "-container" %}
|
29
29
|
{% set add_id = widget.id + "-add" %}
|
30
30
|
{% set vals = 'js:{"name": '+ fnGetName + '(), "token": "' + type.token + '", "removable": true}' %}
|
31
|
-
<Button type="button" target={container_id} swap="beforeend" id={add_id} vals={vals} get={type.url}>
|
31
|
+
<Button type="button" hx-target={container_id} hx-swap="beforeend" id={add_id} hx-vals={vals} hx-get={type.url}>
|
32
32
|
Add
|
33
33
|
</Button>
|
34
34
|
</div>
|
@@ -5,8 +5,6 @@
|
|
5
5
|
<Label for={widget.id}>{{widget.title}}</Label>
|
6
6
|
<Input name={widget.name} value={widget.value} type={widget.input_type} id={widget.id}
|
7
7
|
aria-label={widget.aria_label} placeholder={widget.placeholder} />
|
8
|
-
{
|
9
|
-
<span class="mt-2 text-sm text-neutral-500 dark:text-neutral-400">{{widget.help_text}}</span>
|
10
|
-
{%- endif %}
|
8
|
+
<pydantic_form.Hint text={widget.hint} />
|
11
9
|
</div>
|
12
10
|
</pydantic_form.Widget>
|
@@ -4,21 +4,21 @@
|
|
4
4
|
<div id="{{widget.id}}">
|
5
5
|
<details open>
|
6
6
|
<summary class="justify-between items-center font-medium cursor-pointer">
|
7
|
-
<
|
7
|
+
<H3>{{widget.title}}</H3>
|
8
8
|
</summary>
|
9
9
|
<div hx-sync="this" id="{{widget.id}}-child">
|
10
10
|
{% if child %}
|
11
11
|
{{ child }}
|
12
12
|
{% else %}
|
13
13
|
{% for typ in types %}
|
14
|
-
<Button type="button" target="closest div" get={typ.url} vals={typ.params|tojson}
|
15
|
-
id={typ.
|
14
|
+
<Button type="button" hx-target="closest div" hx-get={typ.url} hx-vals={typ.params|tojson}
|
15
|
+
id={typ.id}
|
16
16
|
onclick={"document.getElementById('" + widget.id +"-remove-btn').hidden=false"}>{{typ.title}}</Button>
|
17
17
|
{% endfor %}
|
18
18
|
{% endif %}
|
19
19
|
</div>
|
20
|
-
<Button type="button" id={widget.id + "-remove-btn" } target={"#" + widget.id} vals={parent_type.params|tojson}
|
21
|
-
get={parent_type.url} hidden={not child}>
|
20
|
+
<Button type="button" id={widget.id + "-remove-btn" } hx-target={"#" + widget.id} hx-vals={parent_type.params|tojson}
|
21
|
+
hx-get={parent_type.url} hidden={not child}>
|
22
22
|
Remove
|
23
23
|
</Button>
|
24
24
|
</details>
|
fastlife/templating/__init__.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from .binding import Template, template
|
2
|
-
from .renderer import
|
2
|
+
from .renderer import AbstractTemplateRendererFactory, JinjaxTemplateRenderer
|
3
3
|
|
4
4
|
__all__ = [
|
5
|
-
"
|
5
|
+
"AbstractTemplateRendererFactory",
|
6
6
|
"JinjaxTemplateRenderer",
|
7
7
|
"Template",
|
8
8
|
"template",
|
fastlife/templating/binding.py
CHANGED
@@ -9,9 +9,7 @@ Template = Callable[..., Response]
|
|
9
9
|
TemplateEngine = Callable[["Registry", Request], Template]
|
10
10
|
|
11
11
|
|
12
|
-
def
|
13
|
-
template: str, *, content_type: str = "text/html"
|
14
|
-
) -> TemplateEngine:
|
12
|
+
def get_template(template: str, *, content_type: str = "text/html") -> TemplateEngine:
|
15
13
|
def render_template(
|
16
14
|
reg: "Registry",
|
17
15
|
request: Request,
|
@@ -23,7 +21,7 @@ def get_page_template(
|
|
23
21
|
request.cookies.get(reg.settings.csrf_token_name)
|
24
22
|
or _create_csrf_token()
|
25
23
|
)
|
26
|
-
data = reg.renderer.
|
24
|
+
data = reg.renderer(request).render_template(template, **kwargs)
|
27
25
|
resp = Response(data, headers={"Content-Type": content_type})
|
28
26
|
resp.set_cookie(
|
29
27
|
reg.settings.csrf_token_name,
|
@@ -39,21 +37,5 @@ def get_page_template(
|
|
39
37
|
return render_template
|
40
38
|
|
41
39
|
|
42
|
-
def
|
43
|
-
|
44
|
-
) -> Callable[["Registry"], Template]:
|
45
|
-
def render_template(reg: "Registry") -> Template:
|
46
|
-
def parametrizer(**kwargs: Any) -> Response:
|
47
|
-
data = reg.renderer.render_template(template, **kwargs)
|
48
|
-
resp = Response(data, headers={"Content-Type": content_type})
|
49
|
-
return resp
|
50
|
-
|
51
|
-
return parametrizer
|
52
|
-
|
53
|
-
return render_template
|
54
|
-
|
55
|
-
|
56
|
-
def template(template_path: str, page: bool = True) -> Template:
|
57
|
-
return Depends(
|
58
|
-
get_page_template(template_path) if page else get_template(template_path)
|
59
|
-
)
|
40
|
+
def template(template_path: str) -> Template:
|
41
|
+
return Depends(get_template(template_path))
|
@@ -1,4 +1,7 @@
|
|
1
|
-
from .abstract import
|
1
|
+
from .abstract import AbstractTemplateRendererFactory
|
2
2
|
from .jinjax import JinjaxTemplateRenderer
|
3
3
|
|
4
|
-
__all__ = [
|
4
|
+
__all__ = [
|
5
|
+
"AbstractTemplateRendererFactory",
|
6
|
+
"JinjaxTemplateRenderer",
|
7
|
+
]
|
@@ -8,11 +8,7 @@ from pydantic.fields import FieldInfo
|
|
8
8
|
|
9
9
|
class AbstractTemplateRenderer(abc.ABC):
|
10
10
|
route_prefix: str
|
11
|
-
"""Used to
|
12
|
-
|
13
|
-
@abc.abstractmethod
|
14
|
-
def render_page(self, request: Request, template: str, **params: Any) -> str:
|
15
|
-
...
|
11
|
+
"""Used to buid pydantic form"""
|
16
12
|
|
17
13
|
@abc.abstractmethod
|
18
14
|
def render_template(self, template: str, **params: Any) -> str:
|
@@ -29,3 +25,9 @@ class AbstractTemplateRenderer(abc.ABC):
|
|
29
25
|
field: FieldInfo | None = None,
|
30
26
|
) -> Markup:
|
31
27
|
...
|
28
|
+
|
29
|
+
|
30
|
+
class AbstractTemplateRendererFactory(abc.ABC):
|
31
|
+
@abc.abstractmethod
|
32
|
+
def __call__(self, request: Request) -> AbstractTemplateRenderer:
|
33
|
+
...
|