web/formfields.py
changeset 3388 b8be8fc77c27
parent 3347 428f95118556
parent 3387 a357d4147eee
child 3451 6b46d73823f5
--- a/web/formfields.py	Tue Sep 22 12:11:12 2009 +0200
+++ b/web/formfields.py	Tue Sep 22 13:08:42 2009 +0200
@@ -214,6 +214,21 @@
         """
         pass
 
+    def process_form_value(self, form):
+        """process posted form and return correctly typed value"""
+        widget = self.get_widget(form)
+        return widget.process_field_data(form, self)
+
+    def process_posted(self, form):
+        for field in self.actual_fields(form):
+            if field is self:
+                yield field.name, field.process_form_value(form)
+            else:
+                # recursive function: we might have compound fields
+                # of compound fields (of compound fields of ...)
+                for fieldname, value in field.process_posted(form):
+                    yield fieldname, value
+
 
 class StringField(Field):
     widget = TextArea
@@ -286,6 +301,7 @@
                 fkwargs['choices'] = fcstr.vocabulary(form=form)
                 fkwargs['internationalizable'] = True
                 fkwargs['initial'] = lambda f: f.form_field_format(self)
+            fkwargs['eidparam'] = self.eidparam
             field = StringField(name=self.name + '_format', **fkwargs)
             req.data[self] = field
             return field
@@ -361,6 +377,25 @@
                 + renderer.render_help(form, field)
                 + u'<br/>')
 
+    def process_form_value(self, form):
+        posted = form.req.form
+        value = posted.get(form.form_field_name(self))
+        formkey = form.form_field_name(self)
+        if ('%s__detach' % form.context[self]['name']) in posted:
+            # drop current file value
+            value = None
+        # no need to check value when nor explicit detach nor new file
+        # submitted, since it will think the attribute is not modified
+        elif value:
+            filename, _, stream = value
+            # value is a  3-uple (filename, mimetype, stream)
+            value = Binary(stream.read())
+            if not val.getvalue(): # usually an unexistant file
+                value = None
+            else:
+                value.filename = filename
+        return value
+
 
 class EditableFileField(FileField):
     editable_formats = ('text/plain', 'text/html', 'text/rest')
@@ -391,6 +426,14 @@
                     # XXX restore form context?
         return '\n'.join(wdgs)
 
+    def process_form_value(self, form):
+        value = form.req.form.get(form.form_field_name(self))
+        if isinstance(value, unicode):
+            # file modified using a text widget
+            encoding = form.form_field_encoding(self)
+            return Binary(value.encode(encoding))
+        return super(EditableFileField, self).process_form_value(form)
+
 
 class IntField(Field):
     def __init__(self, min=None, max=None, **kwargs):
@@ -401,6 +444,8 @@
             self.widget.attrs.setdefault('size', 5)
             self.widget.attrs.setdefault('maxlength', 15)
 
+    def process_form_value(self, form):
+        return int(Field.process_form_value(self, form))
 
 class BooleanField(Field):
     widget = Radio
@@ -410,6 +455,8 @@
             return self.choices
         return [(form.req._('yes'), '1'), (form.req._('no'), '')]
 
+    def process_form_value(self, form):
+        return bool(Field.process_form_value(self, form))
 
 class FloatField(IntField):
     def format_single_value(self, req, value):
@@ -421,6 +468,8 @@
     def render_example(self, req):
         return self.format_single_value(req, 1.234)
 
+    def process_form_value(self, form):
+        return float(Field.process_form_value(self, form))
 
 class DateField(StringField):
     format_prop = 'ui.date-format'
@@ -432,26 +481,39 @@
     def render_example(self, req):
         return self.format_single_value(req, datetime.now())
 
+    def process_form_value(self, form):
+        # widget is supposed to return a date as a correctly formatted string
+        date = Field.process_form_value(self, form)
+        # but for some widgets, it might be simpler to return date objects
+        # directly, so handle that case :
+        if isinstance(date, basestring):
+            date = form.parse_date(wdgdate, 'Date')
+        return date
 
 class DateTimeField(DateField):
     format_prop = 'ui.datetime-format'
 
+    def process_form_value(self, form):
+        # widget is supposed to return a date as a correctly formatted string
+        date = Field.process_form_value(self, form)
+        # but for some widgets, it might be simpler to return date objects
+        # directly, so handle that case :
+        if isinstance(date, basestring):
+            date = form.parse_datetime(wdgdate, 'Datetime')
+        return date
 
 class TimeField(DateField):
     format_prop = 'ui.time-format'
     widget = TextInput
 
-
-class HiddenInitialValueField(Field):
-    def __init__(self, visible_field):
-        name = 'edit%s-%s' % (visible_field.role[0], visible_field.name)
-        super(HiddenInitialValueField, self).__init__(
-            name=name, widget=HiddenInput, eidparam=True)
-        self.visible_field = visible_field
-
-    def format_single_value(self, req, value):
-        return self.visible_field.format_single_value(req, value)
-
+    def process_form_value(self, form):
+        # widget is supposed to return a date as a correctly formatted string
+        time = Field.process_form_value(self, form)
+        # but for some widgets, it might be simpler to return time objects
+        # directly, so handle that case :
+        if isinstance(time, basestring):
+            time = form.parse_time(wdgdate, 'Time')
+        return time
 
 class RelationField(Field):
     # XXX (syt): iirc, we originaly don't sort relation vocabulary since we want
@@ -533,6 +595,7 @@
         kwargs['label'] = (eschema.type + '_object', rschema.type)
     else:
         kwargs['label'] = (eschema.type, rschema.type)
+    kwargs['eidparam'] = True
     kwargs.setdefault('help', help)
     if rschema.is_final():
         if skip_meta_attr and rschema in eschema.meta_attributes():