Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/wtforms/fields/form.py: 32%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from wtforms.utils import unset_value
3from .. import widgets
4from .core import Field
6__all__ = ("FormField",)
9class FormField(Field):
10 """
11 Encapsulate a form as a field in another form.
13 :param form_class:
14 A subclass of Form that will be encapsulated.
15 :param separator:
16 A string which will be suffixed to this field's name to create the
17 prefix to enclosed fields. The default is fine for most uses.
18 """
20 widget = widgets.TableWidget()
22 def __init__(
23 self, form_class, label=None, validators=None, separator="-", **kwargs
24 ):
25 super().__init__(label, validators, **kwargs)
26 self.form_class = form_class
27 self.separator = separator
28 self._obj = None
29 if self.filters:
30 raise TypeError(
31 "FormField cannot take filters, as the encapsulated"
32 " data is not mutable."
33 )
34 if validators:
35 raise TypeError(
36 "FormField does not accept any validators. Instead,"
37 " define them on the enclosed form."
38 )
40 def process(self, formdata, data=unset_value, extra_filters=None):
41 if extra_filters:
42 raise TypeError(
43 "FormField cannot take filters, as the encapsulateddata is not mutable."
44 )
46 if data is unset_value:
47 try:
48 data = self.default()
49 except TypeError:
50 data = self.default
51 self._obj = data
53 self.object_data = data
55 prefix = self.name + self.separator
56 if isinstance(data, dict):
57 user_meta = data.get("meta") or {}
58 data_kwargs = {k: v for k, v in data.items() if k != "meta"}
59 self.form = self.form_class(
60 formdata=formdata,
61 prefix=prefix,
62 meta={**user_meta, "_parent_form": self._form},
63 **data_kwargs,
64 )
65 else:
66 self.form = self.form_class(
67 formdata=formdata,
68 obj=data,
69 prefix=prefix,
70 meta={"_parent_form": self._form},
71 )
73 def post_process(self):
74 self.form.post_process()
76 def validate(self, form, extra_validators=()):
77 if extra_validators:
78 raise TypeError(
79 "FormField does not accept in-line validators, as it"
80 " gets errors from the enclosed form."
81 )
82 return self.form.validate()
84 def populate_obj(self, obj, name):
85 candidate = getattr(obj, name, None)
86 if candidate is None:
87 if self._obj is None:
88 raise TypeError(
89 "populate_obj: cannot find a value to populate from"
90 " the provided obj or input data/defaults"
91 )
92 candidate = self._obj
94 self.form.populate_obj(candidate)
95 setattr(obj, name, candidate)
97 def __iter__(self):
98 return iter(self.form)
100 def __getitem__(self, name):
101 return self.form[name]
103 def __getattr__(self, name):
104 return getattr(self.form, name)
106 @property
107 def data(self):
108 return self.form.data
110 @property
111 def errors(self):
112 return self.form.errors