37 self.value = value |
37 self.value = value |
38 |
38 |
39 super(FormError, self).__init__(error) |
39 super(FormError, self).__init__(error) |
40 |
40 |
41 class BaseForm (object) : |
41 class BaseForm (object) : |
42 # any POST data we have processed, updated from process() |
42 # processed POST data |
43 data = None |
43 data = None |
44 |
44 |
45 def __init__ (self, app) : |
45 def __init__ (self) : |
46 """ |
46 """ |
47 app - bind this form to the app state (db etc) |
47 Setup state. |
48 """ |
48 |
49 |
49 Note that a Form is stateful, and should only be used for one form transaction. |
50 self.app = app |
50 """ |
51 |
51 |
52 # accumulated errors |
52 # accumulated errors |
53 self.errors = collections.defaultdict(list) |
53 self.errors = collections.defaultdict(list) |
54 |
54 |
55 def defaults (self) : |
55 def defaults (self) : |
128 |
128 |
129 def process_integer_field (self, name, default=None, required=None) : |
129 def process_integer_field (self, name, default=None, required=None) : |
130 """ |
130 """ |
131 Process a generic incoming int field. |
131 Process a generic incoming int field. |
132 |
132 |
|
133 If the field is empty, uses the default value. |
|
134 |
133 Returns the value as int, or default. |
135 Returns the value as int, or default. |
134 """ |
136 """ |
135 |
137 |
136 value = self.process_raw_field(name, required=required) |
138 value = self.process_raw_field(name, required=required) |
137 |
139 |
138 if value is None : |
140 if not value: |
|
141 # not included in POST, or empty |
139 return default |
142 return default |
140 |
143 |
141 try : |
144 try : |
142 return int(value) |
145 return int(value) |
143 |
146 |
198 return self.process_text_field(name, required=required) |
201 return self.process_text_field(name, required=required) |
199 |
202 |
200 else : |
203 else : |
201 # not selected |
204 # not selected |
202 return False |
205 return False |
203 |
206 |
|
207 def process_action_field (self, name, required=None) : |
|
208 """ |
|
209 Given a form with multiple named submit buttons, checks if the given one was used to submit the form. |
|
210 |
|
211 If required, raises a FormError if the button wasn't pressed. |
|
212 """ |
|
213 |
|
214 value = self.process_raw_field(name, required) |
|
215 |
|
216 if value and value.strip() : |
|
217 # pressed |
|
218 return True |
|
219 |
|
220 elif required : |
|
221 raise FormError(name, None, "Must be pressed") |
|
222 |
|
223 else : |
|
224 # some other submit was hit |
|
225 return False |
|
226 |
|
227 def process_list_field (self, name, required=None, type=unicode) : |
|
228 """ |
|
229 Process an incoming multi-value field, returning the full list of values, converted using the given converter. |
|
230 |
|
231 Returns an empty list if no incoming values, and not rquired. |
|
232 |
|
233 XXX: doesn't strip() the values |
|
234 """ |
|
235 |
|
236 if name not in self.data and required : |
|
237 # fail |
|
238 raise FormError(name, None, "No values given") |
|
239 |
|
240 elif name not in self.data : |
|
241 # empty/default |
|
242 return [] |
|
243 |
|
244 else : |
|
245 # type'd list of values |
|
246 # uses werkzeug's MultiDict API |
|
247 return self.data.getlist(name, type) |
204 |
248 |
205 def process_multifield (self, table, id, fields) : |
249 def process_multifield (self, table, id, fields) : |
206 """ |
250 """ |
207 Process a set of user-given field values for an object with an unique id, and some set of additional fields. |
251 Process a set of user-given field values for an object with an unique id, and some set of additional fields. |
208 |
252 |
273 data - the submitted POST data as a MultiDict |
317 data - the submitted POST data as a MultiDict |
274 |
318 |
275 Returns True if all fields were processed without errors, False otherwise. |
319 Returns True if all fields were processed without errors, False otherwise. |
276 """ |
320 """ |
277 |
321 |
|
322 # bind |
|
323 self.data = data |
|
324 |
278 raise NotImplmentedError() |
325 raise NotImplmentedError() |
279 |
326 |
280 return not self.errors |
327 return not self.errors |
281 |
328 |
282 def render_text_input (self, name, value=None, multiline=False, rows=10, autoscale=True) : |
329 def render_text_input (self, name, value=None, multiline=False, rows=10, autoscale=True) : |
375 return tags.input(type='reset', value=value, |
422 return tags.input(type='reset', value=value, |
376 onclick = ( |
423 onclick = ( |
377 "$.redirect('" + return_url + "')" |
424 "$.redirect('" + return_url + "')" |
378 ) if return_url else None, |
425 ) if return_url else None, |
379 ) |
426 ) |
380 |
427 |
|
428 def render_submit_button (self, value, name=None) : |
|
429 """ |
|
430 Render HTML for a <input type="submit">. |
|
431 |
|
432 value - button title |
|
433 name - optionally give the button a name for use with process_action_field |
|
434 """ |
|
435 |
|
436 return tags.input(type='submit', name=name, value=value) |
381 |
437 |
382 def render_form_field (self, name, title, description, inputs) : |
438 def render_form_field (self, name, title, description, inputs) : |
383 """ |
439 """ |
384 Render the label, input control, error note and description for a single field, along with their containing <li>. |
440 Render the label, input control, error note and description for a single field, along with their containing <li>. |
385 """ |
441 """ |