fastlifeweb 0.3.0__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.
Files changed (47) hide show
  1. fastlife/configurator/registry.py +2 -2
  2. fastlife/configurator/settings.py +3 -0
  3. fastlife/templates/A.jinja +30 -4
  4. fastlife/templates/Button.jinja +31 -17
  5. fastlife/templates/Checkbox.jinja +20 -2
  6. fastlife/templates/CsrfToken.jinja +0 -1
  7. fastlife/templates/Form.jinja +9 -3
  8. fastlife/templates/H1.jinja +15 -4
  9. fastlife/templates/H2.jinja +15 -4
  10. fastlife/templates/H3.jinja +14 -0
  11. fastlife/templates/H4.jinja +14 -0
  12. fastlife/templates/H5.jinja +14 -0
  13. fastlife/templates/H6.jinja +14 -0
  14. fastlife/templates/Input.jinja +29 -6
  15. fastlife/templates/Label.jinja +10 -2
  16. fastlife/templates/Option.jinja +4 -2
  17. fastlife/templates/P.jinja +9 -0
  18. fastlife/templates/Radio.jinja +29 -7
  19. fastlife/templates/Select.jinja +25 -6
  20. fastlife/templates/pydantic_form/Boolean.jinja +1 -1
  21. fastlife/templates/pydantic_form/Dropdown.jinja +4 -6
  22. fastlife/templates/pydantic_form/Hint.jinja +4 -0
  23. fastlife/templates/pydantic_form/Model.jinja +1 -1
  24. fastlife/templates/pydantic_form/Sequence.jinja +3 -3
  25. fastlife/templates/pydantic_form/Text.jinja +1 -3
  26. fastlife/templates/pydantic_form/Union.jinja +5 -5
  27. fastlife/templating/__init__.py +2 -2
  28. fastlife/templating/binding.py +4 -22
  29. fastlife/templating/renderer/__init__.py +5 -2
  30. fastlife/templating/renderer/abstract.py +7 -5
  31. fastlife/templating/renderer/jinjax.py +51 -23
  32. fastlife/templating/renderer/widgets/base.py +12 -2
  33. fastlife/templating/renderer/widgets/boolean.py +4 -3
  34. fastlife/templating/renderer/widgets/dropdown.py +7 -6
  35. fastlife/templating/renderer/widgets/factory.py +38 -21
  36. fastlife/templating/renderer/widgets/hidden.py +2 -3
  37. fastlife/templating/renderer/widgets/model.py +7 -6
  38. fastlife/templating/renderer/widgets/sequence.py +8 -9
  39. fastlife/templating/renderer/widgets/text.py +9 -5
  40. fastlife/templating/renderer/widgets/union.py +7 -6
  41. fastlife/testing/testclient.py +116 -55
  42. fastlife/views/pydantic_form.py +5 -2
  43. {fastlifeweb-0.3.0.dist-info → fastlifeweb-0.4.0.dist-info}/METADATA +6 -5
  44. fastlifeweb-0.4.0.dist-info/RECORD +69 -0
  45. fastlifeweb-0.3.0.dist-info/RECORD +0 -63
  46. {fastlifeweb-0.3.0.dist-info → fastlifeweb-0.4.0.dist-info}/LICENSE +0 -0
  47. {fastlifeweb-0.3.0.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
- AbstractTemplateRenderer, # coverage: ignore
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: "AbstractTemplateRenderer"
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="")
@@ -1,5 +1,31 @@
1
- {# def href, target="#maincontent", swap="innerHTML show:body:top", push_url=true #}
2
- <a href="{{href}}" hx-get="{{href}}" hx-target="{{target}}" hx-swap="{{swap}}" {% if push_url %}hx-push-url="true" {%- endif %}
3
- class="text-neutral-900 bg-neutral-200 hover:bg-neutral-50 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-neutral-400 dark:hover:bg-neutral-300 dark:focus:ring-neutral-100">
4
- {{ content }}
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>
@@ -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
- target="",
8
- swap="",
9
- get="",
10
- select="",
11
- after_request="",
12
- vals="",
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
- hidden=false,
15
- aria_label=""
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
- target%}hx-target="{{target}}" {% endif %} {% if swap %}hx-swap="{{swap}}" {% endif %} {% if select
22
- %}hx-select="{{select}}" {% endif %} {% if get %}hx-get="{{get}}" {% endif %} {% if onclick %}onclick="{{onclick}}" {%
23
- endif %}{% if after_request %}hx-on::after-request="{{after_request}}" {% endif %} {% if vals
24
- %}hx-vals='{{vals|safe}}' {% endif %} {% if aria_label %}aria-label="{{aria_label}}" {% endif %}
25
- class="{% if full_width %}w-full {% endif %}{{css}}" {% if hidden %}hidden{% 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 name, value, id #}
2
- <input name="{{name}}" value="{{value}}" type="checkbox" id="{{id}}" />
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_}}" />
@@ -1,2 +1 @@
1
- {# def csrf_token #}
2
1
  <Hidden name={csrf_token.name} value={csrf_token.value} />
@@ -1,5 +1,11 @@
1
- {# def csrf_token #}
2
- <form class="space-y-4 md:space-y-6" hx-post="" method="post">
3
- <CsrfToken csrf_token={csrf_token}/>
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>
@@ -1,4 +1,15 @@
1
- <h1
2
- class="block pb-4 font-sans text-5xl font-bold leading-tight tracking-tight text-neutral-900 md:text-4xl dark:text-white">
3
- {{ content }}
4
- </h1>
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>
@@ -1,4 +1,15 @@
1
- <h2
2
- class="block pb-4 font-sans text-4xl font-bold leading-tight tracking-tight text-neutral-900 md:text-4xl dark:text-white">
3
- {{ content }}
4
- </h2>
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>
@@ -0,0 +1,14 @@
1
+ {# def
2
+ class_="""
3
+ block
4
+ font-bold
5
+ font-sans
6
+ leading-tight
7
+ pb-4
8
+ text-3xl
9
+ text-neutral-900
10
+ tracking-tight
11
+ dark:text-white
12
+ md:text-3xl"""
13
+ #}
14
+ <h3 class="{{attrs.class or class_}}">{{ content }}</h3>
@@ -0,0 +1,14 @@
1
+ {# def
2
+ class_="""
3
+ block
4
+ font-bold
5
+ font-sans
6
+ leading-tight
7
+ pb-4
8
+ text-2xl
9
+ text-neutral-900
10
+ tracking-tight
11
+ dark:text-white
12
+ md:text-2xl"""
13
+ #}
14
+ <h4 class="{{attrs.class or class_}}">{{ content }}</h4>
@@ -0,0 +1,14 @@
1
+ {# def
2
+ class_="""
3
+ block
4
+ font-bold
5
+ font-sans
6
+ leading-tight
7
+ pb-4
8
+ text-xl
9
+ text-neutral-900
10
+ tracking-tight
11
+ dark:text-white
12
+ md:text-xl"""
13
+ #}
14
+ <h5 class="{{attrs.class or class_}}">{{ content }}</h5>
@@ -0,0 +1,14 @@
1
+ {# def
2
+ class_="""
3
+ block
4
+ font-bold
5
+ font-sans
6
+ leading-tight
7
+ pb-4
8
+ text-l
9
+ text-neutral-900
10
+ tracking-tight
11
+ dark:text-white
12
+ md:text-l"""
13
+ #}
14
+ <h6 class="{{attrs.class or class_}}">{{ content }}</h6>
@@ -1,8 +1,31 @@
1
- {# def name, value="", input_type="text", id="", aria_label="", placeholder="" #}
2
- {% set css = "bg-neutral-50 border border-neutral-300 text-neutral-900 text-base rounded-lg focus:ring-primary-500
3
- focus:border-primary-500 block w-full p-2.5 dark:bg-neutral-700 dark:border-neutral-600 dark:placeholder-neutral-400
4
- dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %}
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="{{input_type}}" id="{{id}}" {% if aria_label
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="{{css}}" />
31
+ class="{{attrs.class or class_}}" />
@@ -1,3 +1,11 @@
1
- {%- set css ="block mb-2 text-base font-bold text-neutral-900 dark:text-white" -%}
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="{{css}}">{{content}}</label>
11
+ <label for="{{attrs.for}}" class="{{attrs.class or class_}}">{{content}}</label>
@@ -1,2 +1,4 @@
1
- {# def value #}
2
- <option value="{{value}}">{{ content }}</option>
1
+ {# def value, selected=False #}
2
+ <option value="{{value}}" {%if selected%}selected{% endif%}>
3
+ {{- content -}}
4
+ </option>
@@ -0,0 +1,9 @@
1
+ {# def
2
+ id="",
3
+ class_="""
4
+ text-base
5
+ text-neutral-900
6
+ dark:text-white
7
+ """
8
+ #}
9
+ <p {% if id %}id="{{id}}" {% endif %} class="{{ attrs.class or class_}}">{{content}}</p>
@@ -1,8 +1,30 @@
1
- {# def label name id value checked=false disabled=false onclick="" #}
2
- <div class="flex items-center mb-4">
3
- <input type="radio" name="{{name}}" id="{{id}}" {% if value %}value="{{value}}" {% endif %}{% if checked %}checked{%
4
- endif %}
5
- class="w-4 h-4 text-primary-600 bg-neutral-100 border-neutral-300 focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-neutral-800 focus:ring-2 dark:bg-neutral-700 dark:border-neutral-600"
6
- {% if onclick %}onclick="{{onclick}}" {% endif %} {%if disabled%}disabled{%endif%}>
7
- <label for="{{id}}" class="ms-2 text-sm font-medium text-neutral-900 dark:text-neutral-300">{{label}}</label>
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>
@@ -1,8 +1,27 @@
1
- {# def name, id #}
2
- {% set css = "bg-neutral-50 border border-neutral-300 text-neutral-900 text-base rounded-lg focus:ring-primary-500
3
- focus:border-primary-500 block w-full p-2.5 dark:bg-neutral-700 dark:border-neutral-600 dark:placeholder-neutral-400
4
- dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" %}
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="{{css}}">
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} value={widget.value} type="checkbox" id={widget.id} />
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
- <Option value={opt.value}>
9
- {{ opt.text }}
10
- </Option>
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
- {%- if widget.help_text -%}
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>
@@ -0,0 +1,4 @@
1
+ {# def text #}
2
+ {% if text %}
3
+ <span class="mt-2 text-sm text-neutral-500 dark:text-neutral-400">{{text}}</span>
4
+ {% endif %}
@@ -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
- <h4 class="inline font-sans text-3xl font-bold">{{widget.title}}</h4>
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
- <h4 class="inline font-sans text-3xl font-bold">{{widget.title}}</h4>
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
- {%- if widget.help_text -%}
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
- <h4 class="inline font-sans text-3xl font-bold">{{widget.title}}</h4>
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.fullname + "-" + widget.token}
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 AbstractTemplateRenderer, JinjaxTemplateRenderer
2
+ from .renderer import AbstractTemplateRendererFactory, JinjaxTemplateRenderer
3
3
 
4
4
  __all__ = [
5
- "AbstractTemplateRenderer",
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 get_page_template(
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.render_page(request, template, **kwargs)
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 get_template(
43
- template: str, *, content_type: str = "text/html"
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 AbstractTemplateRenderer
1
+ from .abstract import AbstractTemplateRendererFactory
2
2
  from .jinjax import JinjaxTemplateRenderer
3
3
 
4
- __all__ = ["AbstractTemplateRenderer", "JinjaxTemplateRenderer"]
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 prefix url to fetch fast life widgets."""
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
+ ...