-
Notifications
You must be signed in to change notification settings - Fork 336
/
Copy pathforms.py
128 lines (95 loc) · 4.27 KB
/
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import typing as _t
from abc import ABC
import pydantic
import typing_extensions as _te
from .. import class_name as _class_name
from .. import events, forms
from .. import types as _types
if _t.TYPE_CHECKING:
from . import AnyComponent
InputHtmlType = _t.Literal['text', 'date', 'datetime-local', 'time', 'email', 'url', 'number', 'password', 'hidden']
class BaseFormField(pydantic.BaseModel, ABC, defer_build=True):
name: str
title: _t.Union[_t.List[str], str]
required: bool = False
error: _t.Union[str, None] = None
locked: bool = False
description: _t.Union[str, None] = None
display_mode: _t.Union[_t.Literal['default', 'inline'], None] = pydantic.Field(
default=None, serialization_alias='displayMode'
)
class_name: _class_name.ClassNameField = None
class FormFieldInput(BaseFormField):
html_type: InputHtmlType = pydantic.Field(default='text', serialization_alias='htmlType')
initial: _t.Union[str, float, None] = None
placeholder: _t.Union[str, None] = None
type: _t.Literal['FormFieldInput'] = 'FormFieldInput'
class FormFieldTextarea(BaseFormField):
rows: _t.Union[int, None] = None
cols: _t.Union[int, None] = None
initial: _t.Union[str, None] = None
placeholder: _t.Union[str, None] = None
type: _t.Literal['FormFieldTextarea'] = 'FormFieldTextarea'
class FormFieldBoolean(BaseFormField):
initial: _t.Union[bool, None] = None
mode: _t.Literal['checkbox', 'switch'] = 'checkbox'
type: _t.Literal['FormFieldBoolean'] = 'FormFieldBoolean'
class FormFieldFile(BaseFormField):
multiple: _t.Union[bool, None] = None
accept: _t.Union[str, None] = None
type: _t.Literal['FormFieldFile'] = 'FormFieldFile'
class FormFieldSelect(BaseFormField):
options: forms.SelectOptions
multiple: _t.Union[bool, None] = None
initial: _t.Union[_t.List[str], str, None] = None
vanilla: _t.Union[bool, None] = None
placeholder: _t.Union[str, None] = None
type: _t.Literal['FormFieldSelect'] = 'FormFieldSelect'
class FormFieldSelectSearch(BaseFormField):
search_url: str = pydantic.Field(serialization_alias='searchUrl')
multiple: _t.Union[bool, None] = None
initial: _t.Union[forms.SelectOption, None] = None
# time in ms to debounce requests by, defaults to 300ms
debounce: _t.Union[int, None] = None
placeholder: _t.Union[str, None] = None
type: _t.Literal['FormFieldSelectSearch'] = 'FormFieldSelectSearch'
class FormFieldRadio(BaseFormField):
options: forms.SelectOptions
initial: _t.Union[str, None] = None
type: _t.Literal['FormFieldRadio'] = 'FormFieldRadio'
FormField = _t.Union[
FormFieldInput,
FormFieldTextarea,
FormFieldBoolean,
FormFieldFile,
FormFieldSelect,
FormFieldSelectSearch,
FormFieldRadio,
]
class BaseForm(pydantic.BaseModel, ABC, defer_build=True, extra='forbid'):
submit_url: str = pydantic.Field(serialization_alias='submitUrl')
initial: _t.Union[_t.Dict[str, _types.JsonData], None] = None
method: _t.Literal['POST', 'GOTO', 'GET'] = 'POST'
display_mode: _t.Union[_t.Literal['default', 'inline'], None] = pydantic.Field(
default=None, serialization_alias='displayMode'
)
submit_on_change: _t.Union[bool, None] = pydantic.Field(default=None, serialization_alias='submitOnChange')
submit_trigger: _t.Union[events.PageEvent, None] = pydantic.Field(default=None, serialization_alias='submitTrigger')
footer: '_t.Union[_t.List[AnyComponent], None]' = None
class_name: _class_name.ClassNameField = None
@pydantic.model_validator(mode='after')
def default_footer(self) -> _te.Self:
if self.footer is None and self.display_mode == 'inline':
self.footer = []
return self
class Form(BaseForm):
form_fields: _t.List[FormField] = pydantic.Field(serialization_alias='formFields')
type: _t.Literal['Form'] = 'Form'
FormFieldsModel = _t.TypeVar('FormFieldsModel', bound=pydantic.BaseModel)
class ModelForm(BaseForm):
model: _t.Type[pydantic.BaseModel] = pydantic.Field(exclude=True)
type: _t.Literal['ModelForm'] = 'ModelForm'
@pydantic.computed_field(alias='formFields')
def form_fields(self) -> _t.List[FormField]:
from ..json_schema import model_json_schema_to_fields
return model_json_schema_to_fields(self.model)