fastlifeweb 0.3.1__tar.gz → 0.4.0__tar.gz
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.
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/PKG-INFO +5 -4
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/README.md +0 -2
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/pyproject.toml +5 -2
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/configurator/registry.py +2 -2
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/configurator/settings.py +3 -0
- fastlifeweb-0.4.0/src/fastlife/templates/A.jinja +31 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Button.jinja +41 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Checkbox.jinja +20 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/CsrfToken.jinja +0 -1
- fastlifeweb-0.4.0/src/fastlife/templates/Form.jinja +11 -0
- fastlifeweb-0.4.0/src/fastlife/templates/H1.jinja +15 -0
- fastlifeweb-0.4.0/src/fastlife/templates/H2.jinja +15 -0
- fastlifeweb-0.4.0/src/fastlife/templates/H3.jinja +14 -0
- fastlifeweb-0.4.0/src/fastlife/templates/H4.jinja +14 -0
- fastlifeweb-0.4.0/src/fastlife/templates/H5.jinja +14 -0
- fastlifeweb-0.4.0/src/fastlife/templates/H6.jinja +14 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Input.jinja +31 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Label.jinja +11 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Option.jinja +4 -0
- fastlifeweb-0.4.0/src/fastlife/templates/P.jinja +9 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Radio.jinja +30 -0
- fastlifeweb-0.4.0/src/fastlife/templates/Select.jinja +27 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Boolean.jinja +1 -1
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Dropdown.jinja +4 -6
- fastlifeweb-0.4.0/src/fastlife/templates/pydantic_form/Hint.jinja +4 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Model.jinja +1 -1
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Sequence.jinja +3 -3
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Text.jinja +1 -3
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Union.jinja +5 -5
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/__init__.py +2 -2
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/binding.py +4 -22
- fastlifeweb-0.4.0/src/fastlife/templating/renderer/__init__.py +7 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/abstract.py +7 -5
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/jinjax.py +51 -23
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/base.py +12 -2
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/boolean.py +4 -3
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/dropdown.py +7 -6
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/factory.py +38 -21
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/hidden.py +2 -3
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/model.py +7 -6
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/sequence.py +8 -9
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/text.py +9 -5
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/union.py +7 -6
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/testing/testclient.py +116 -55
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/views/pydantic_form.py +5 -2
- fastlifeweb-0.3.1/src/fastlife/templates/A.jinja +0 -5
- fastlifeweb-0.3.1/src/fastlife/templates/Button.jinja +0 -27
- fastlifeweb-0.3.1/src/fastlife/templates/Checkbox.jinja +0 -2
- fastlifeweb-0.3.1/src/fastlife/templates/Form.jinja +0 -5
- fastlifeweb-0.3.1/src/fastlife/templates/H1.jinja +0 -4
- fastlifeweb-0.3.1/src/fastlife/templates/H2.jinja +0 -4
- fastlifeweb-0.3.1/src/fastlife/templates/Input.jinja +0 -8
- fastlifeweb-0.3.1/src/fastlife/templates/Label.jinja +0 -3
- fastlifeweb-0.3.1/src/fastlife/templates/Option.jinja +0 -2
- fastlifeweb-0.3.1/src/fastlife/templates/Radio.jinja +0 -8
- fastlifeweb-0.3.1/src/fastlife/templates/Select.jinja +0 -8
- fastlifeweb-0.3.1/src/fastlife/templating/renderer/__init__.py +0 -4
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/LICENSE +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/configurator/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/configurator/base.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/configurator/configurator.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/py.typed +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/request/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/request/form_data.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/security/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/security/csrf.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/security/policy.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/session/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/session/middleware.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/session/serializer.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/shared_utils/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/shared_utils/infer.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/shared_utils/resolver.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/Hidden.jinja +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Hidden.jinja +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templates/pydantic_form/Widget.jinja +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/templating/renderer/widgets/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/testing/__init__.py +0 -0
- {fastlifeweb-0.3.1 → fastlifeweb-0.4.0}/src/fastlife/views/__init__.py +0 -0
@@ -1,7 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fastlifeweb
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Summary: High-level web framework
|
5
|
+
Home-page: https://github.com/mardiros/fastlife
|
5
6
|
License: BSD-derived
|
6
7
|
Author: Guillaume Gauvrit
|
7
8
|
Author-email: guillaume@gauvr.it
|
@@ -20,12 +21,14 @@ Requires-Dist: beautifulsoup4[testing] (>=4.12.2,<5.0.0)
|
|
20
21
|
Requires-Dist: behave (>=1.2.6,<2.0.0)
|
21
22
|
Requires-Dist: fastapi (>=0.110.0,<0.111.0)
|
22
23
|
Requires-Dist: itsdangerous (>=2.1.2,<3.0.0)
|
23
|
-
Requires-Dist: jinjax (>=0.
|
24
|
+
Requires-Dist: jinjax (>=0.32,<0.33)
|
24
25
|
Requires-Dist: markupsafe (>=2.1.3,<3.0.0)
|
26
|
+
Requires-Dist: multidict (>=6.0.5,<7.0.0)
|
25
27
|
Requires-Dist: pydantic (>=2.3.0,<3.0.0)
|
26
28
|
Requires-Dist: pydantic-settings (>=2.0.3,<3.0.0)
|
27
29
|
Requires-Dist: python-multipart (>=0.0.6,<0.0.7)
|
28
30
|
Requires-Dist: venusian (>=3.0.0,<4.0.0)
|
31
|
+
Project-URL: Repository, https://github.com/mardiros/fastlife
|
29
32
|
Description-Content-Type: text/markdown
|
30
33
|
|
31
34
|
# Fastlife
|
@@ -44,5 +47,3 @@ Under heavy development.
|
|
44
47
|
|
45
48
|
The package is available on pypi with the name fastlifeweb.
|
46
49
|
|
47
|
-
The name fastlife is squatted and I am tired of PEP 541 requests.
|
48
|
-
|
@@ -4,6 +4,8 @@ description = "High-level web framework"
|
|
4
4
|
name = "fastlifeweb"
|
5
5
|
license = "BSD-derived"
|
6
6
|
packages = [{include = "fastlife", from = "src"}]
|
7
|
+
homepage = "https://github.com/mardiros/fastlife"
|
8
|
+
repository = "https://github.com/mardiros/fastlife"
|
7
9
|
readme = "README.md"
|
8
10
|
classifiers = [
|
9
11
|
"Development Status :: 4 - Beta",
|
@@ -13,13 +15,13 @@ classifiers = [
|
|
13
15
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
14
16
|
"Topic :: Internet :: WWW/HTTP",
|
15
17
|
]
|
16
|
-
version = "0.
|
18
|
+
version = "0.4.0"
|
17
19
|
|
18
20
|
[tool.poetry.dependencies]
|
19
21
|
python = "^3.11"
|
20
22
|
beautifulsoup4 = {version = "^4.12.2", extras = ["testing"]}
|
21
23
|
fastapi = "^0.110.0"
|
22
|
-
jinjax = "^0.
|
24
|
+
jinjax = "^0.32"
|
23
25
|
pydantic = "^2.3.0"
|
24
26
|
pydantic-settings = "^2.0.3"
|
25
27
|
python-multipart = "^0.0.6"
|
@@ -27,6 +29,7 @@ venusian = "^3.0.0"
|
|
27
29
|
markupsafe = "^2.1.3"
|
28
30
|
behave = "^1.2.6"
|
29
31
|
itsdangerous = "^2.1.2"
|
32
|
+
multidict = "^6.0.5"
|
30
33
|
|
31
34
|
[tool.poetry.group.dev.dependencies]
|
32
35
|
beautifulsoup4 = "^4.12.2"
|
@@ -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="")
|
@@ -0,0 +1,31 @@
|
|
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 -}}
|
31
|
+
</a>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
{# def
|
2
|
+
type="submit",
|
3
|
+
id="",
|
4
|
+
name="action",
|
5
|
+
value="submit",
|
6
|
+
hidden=false,
|
7
|
+
aria_label="",
|
8
|
+
onclick="",
|
9
|
+
hx_target="",
|
10
|
+
hx_swap="",
|
11
|
+
hx_get="",
|
12
|
+
hx_select="",
|
13
|
+
hx_after_request="",
|
14
|
+
hx_vals="",
|
15
|
+
full_width=false,
|
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
|
+
"""
|
33
|
+
#}
|
34
|
+
<button type="{{type}}" {%if id %}id="{{id}}" {%endif%} name="{{name}}" value="{{value}}" {% if
|
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 -}}
|
41
|
+
</button>
|
@@ -0,0 +1,20 @@
|
|
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_}}" />
|
@@ -0,0 +1,11 @@
|
|
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 />
|
10
|
+
{{ content }}
|
11
|
+
</form>
|
@@ -0,0 +1,31 @@
|
|
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
|
+
#}
|
28
|
+
|
29
|
+
<input name="{{name}}" value="{{value}}" type="{{type}}" {% if id %}id="{{id}}" {% endif %}{% if aria_label
|
30
|
+
%}aria-label="{{aria_label}}" {% endif %} {% if placeholder %}placeholder="{{placeholder}}" {% endif %}
|
31
|
+
class="{{attrs.class or class_}}" />
|
@@ -0,0 +1,30 @@
|
|
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>
|
30
|
+
</div>
|
@@ -0,0 +1,27 @@
|
|
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
|
+
#}
|
24
|
+
|
25
|
+
<select name="{{name}}" id="{{id}}" class="{{attrs.class or class_}}">
|
26
|
+
{{- content -}}
|
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>
|
@@ -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",
|
@@ -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))
|
@@ -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
|
+
...
|