diff --git a/src/scriptform.py b/src/scriptform.py
index 62bdf89..7f3a7d1 100755
--- a/src/scriptform.py
+++ b/src/scriptform.py
@@ -160,25 +160,32 @@ class FormDefinition:
"""
Validate all relevant fields for this form against form_values.
"""
+ errors = {}
values = {}
- for field_name in form_values:
- if field_name == 'form_name' or \
- form_values[field_name].filename:
- continue
- v = self.validate_field(field_name,
- form_values.getfirst(field_name))
- if v is not None:
- values[field_name] = v
- # Make sure all required fields are there
+ # First make sure all required fields are there
for field in self.fields:
if 'required' in field and \
field['required'] is True and \
- field['name'] not in values:
- raise ValueError(
- "Required field {0} not present".format(field['name']))
+ field['name'] not in form_values:
+ errors.setdefault(field['name'], []).append(
+ "This field is required"
+ )
- return values
+ # Now validate their actual values.
+ for field_name in form_values:
+ if field_name == 'form_name' or \
+ form_values[field_name].filename:
+ continue
+ try:
+ v = self.validate_field(field_name,
+ form_values.getfirst(field_name))
+ if v is not None:
+ values[field_name] = v
+ except Exception, e:
+ errors.setdefault(field_name, []).append(str(e))
+
+ return (errors, values)
def validate_field(self, field_name, value):
"""
@@ -191,36 +198,68 @@ class FormDefinition:
field_type = field_def['type']
validate_cb = getattr(self, 'validate_{0}'.format(field_type), None)
- if not validate_cb:
- return value
- else:
- return validate_cb(field_def, value)
+ return validate_cb(field_def, value)
+
+ def validate_string(self, field_def, value):
+ maxlen = field_def.get('maxlen', None)
+ minlen = field_def.get('minlen', None)
+
+ if minlen is not None and len(value) < minlen:
+ raise Exception("Minimum length is {0}".format(minlen))
+ if maxlen is not None and len(value) > maxlen:
+ raise Exception("Maximum length is {0}".format(maxlen))
+
+ return value
def validate_integer(self, field_def, value):
+ max = field_def.get('max', None)
+ min = field_def.get('min', None)
+
try:
- int(value)
- return value
+ value = int(value)
except ValueError:
- if field_def.get('required', False):
- raise
- return None
+ raise Exception("Must be an integer number")
+
+ if min is not None and value < min:
+ raise Exception("Minimum value is {0}".format(min))
+ if max is not None and value > max:
+ raise Exception("Maximum value is {0}".format(max))
+
+ return int(value)
def validate_float(self, field_def, value):
+ max = field_def.get('max', None)
+ min = field_def.get('min', None)
+
try:
- return float(value)
+ value = float(value)
except ValueError:
- if field_def.get('required', False):
- raise
- return None
+ raise Exception("Must be an real (float) number")
+
+ if min is not None and value < min:
+ raise Exception("Minimum value is {0}".format(min))
+ if max is not None and value > max:
+ raise Exception("Maximum value is {0}".format(max))
+
+ return float(value)
def validate_date(self, field_def, value):
- m = re.match('([0-9]{4})-([0-9]{2})-([0-9]{2})', value)
- if m:
- return value
- elif field_def.get('required', False):
- raise ValueError(
- "Invalid value for date field: {0}".format(value))
- return None
+ max = field_def.get('max', None)
+ min = field_def.get('min', None)
+
+ try:
+ value = datetime.datetime.strptime(value, '%Y-%m-%d').date()
+ except ValueError:
+ raise Exception("Invalid date, must be in form YYYY-MM-DD")
+
+ if min is not None:
+ if value < datetime.datetime.strptime(min, '%Y-%m-%d').date():
+ raise Exception("Minimum value is {0}".format(min))
+ if max is not None:
+ if value > datetime.datetime.strptime(max, '%Y-%m-%d').date():
+ raise Exception("maximum value is {0}".format(max))
+
+ return value
def validate_radio(self, field_def, value):
if not value in [o[0] for o in field_def['options']]:
@@ -377,7 +416,7 @@ class ScriptFormWebApp(WebAppHandler):
self.end_headers()
self.wfile.write(output)
- def h_form(self, form_name):
+ def h_form(self, form_name, errors={}):
if not self.auth():
return
@@ -394,7 +433,7 @@ class ScriptFormWebApp(WebAppHandler):
"radio": '{2}
',
}
- def render_field(field):
+ def render_field(field, errors):
tpl = field_tpl[field['type']]
required = ''
@@ -438,23 +477,35 @@ class ScriptFormWebApp(WebAppHandler):
return ('''
{title}
-{input}
+{input} {errors}
{0}'.format(result['stdout']) - output = ''' - {header} -