# HG changeset patch # User Sylvain Thénault # Date 1264498469 -3600 # Node ID fabc680bb0bf3c167724673dd1002cdb359cc7ca # Parent 9a902670e4fff2e1125809cbd61a9fc2d98cd3b5 fix Bytes submission pb on POST, due to multiple call to field.process_form_value for a same field. In the case of file, stream.read() doesn't return file's data the second time (since the cursor is at the end of the file). Fix this by having a generic process_form_value method that cache field's value in form.formvalues[field] and so _process_form_value is only called once. You should then override that later method on custom fields. diff -r 9a902670e4ff -r fabc680bb0bf web/formfields.py --- a/web/formfields.py Tue Jan 26 10:30:57 2010 +0100 +++ b/web/formfields.py Tue Jan 26 10:34:29 2010 +0100 @@ -337,6 +337,13 @@ def process_form_value(self, form): """process posted form and return correctly typed value""" + try: + return form.formvalues[self] + except KeyError: + value = form.formvalues[self] = self._process_form_value(form) + return value + + def _process_form_value(self, form): widget = self.get_widget(form) return widget.process_field_data(form, self) @@ -533,7 +540,7 @@ + renderer.render_help(form, field) + u'
') - def process_form_value(self, form): + def _process_form_value(self, form): posted = form._cw.form if self.input_name(form, u'__detach') in posted: # drop current file value on explictily asked to detach @@ -585,12 +592,12 @@ # XXX restore form context? return '\n'.join(wdgs) - def process_form_value(self, form): + def _process_form_value(self, form): value = form._cw.form.get(self.input_name(form)) if isinstance(value, unicode): # file modified using a text widget return Binary(value.encode(self.encoding(form))) - return super(EditableFileField, self).process_form_value(form) + return super(EditableFileField, self)._process_form_value(form) class IntField(Field): @@ -602,8 +609,8 @@ self.widget.attrs.setdefault('size', 5) self.widget.attrs.setdefault('maxlength', 15) - def process_form_value(self, form): - value = Field.process_form_value(self, form) + def _process_form_value(self, form): + value = Field._process_form_value(self, form) if value: try: return int(value) @@ -620,8 +627,8 @@ return super(BooleanField, self).vocabulary(form) return [(form._cw._('yes'), '1'), (form._cw._('no'), '')] - def process_form_value(self, form): - return bool(Field.process_form_value(self, form)) + def _process_form_value(self, form): + return bool(Field._process_form_value(self, form)) class FloatField(IntField): @@ -634,8 +641,8 @@ def render_example(self, req): return self.format_single_value(req, 1.234) - def process_form_value(self, form): - value = Field.process_form_value(self, form) + def _process_form_value(self, form): + value = Field._process_form_value(self, form) if value: try: return float(value) @@ -654,9 +661,9 @@ def render_example(self, req): return self.format_single_value(req, datetime.now()) - def process_form_value(self, form): + 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) + 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): @@ -670,9 +677,9 @@ class DateTimeField(DateField): format_prop = 'ui.datetime-format' - def process_form_value(self, form): + 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) + 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): @@ -687,9 +694,9 @@ format_prop = 'ui.time-format' widget = TextInput - def process_form_value(self, form): + 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) + 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): @@ -801,7 +808,7 @@ def format_single_value(self, req, value): return value - def process_form_value(self, form): + def _process_form_value(self, form): """process posted form and return correctly typed value""" widget = self.get_widget(form) values = widget.process_field_data(form, self) diff -r 9a902670e4ff -r fabc680bb0bf web/views/editcontroller.py --- a/web/views/editcontroller.py Tue Jan 26 10:30:57 2010 +0100 +++ b/web/views/editcontroller.py Tue Jan 26 10:34:29 2010 +0100 @@ -145,6 +145,7 @@ formid = self._cw.form.get('__form_id', 'edition') form = self._cw.vreg['forms'].select(formid, self._cw, entity=entity) eid = form.actual_eid(entity.eid) + form.formvalues = {} # init fields value cache try: editedfields = formparams['_cw_edited_fields'] except KeyError: