From bc2a06c019801a512e5a639efd4254f923ecfc86 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 30 Jun 2016 10:37:36 +0200 Subject: [PATCH] [FIX] http, website_form: preserve form input values order By default, werkzeug doesn't preserve the order of the parameters sent to routes. As stated in the werkzeug documentation: ``` parameter_storage_class the class to use for args and form. The default is an ImmutableMultiDict which supports multiple values per key. alternatively it makes sense to use an ImmutableOrderedMultiDict which preserves order or a ImmutableDict which is the fastest but only remembers the last key. It is also possible to use mutable structures, but this is not recommended. New in version 0.6. ``` For some of our use cases, it makes sense to keep the order of the route parameters. e.g. In the website builder, when building a form with a bunch of inputs values that will be concatened in a lead note, the user expects the answer to be displayed in the same order than the form inputs. This change is seen as a bit risky as it could lead to performances issues in the http routes processing, and this is the reason we do not merge this in stable 9.0 at the moment. If needed, it could be back ported later to 9.0, after several weeks/months of testing in this release(saas-10 atm). opw-677508 --- addons/website_form/controllers/main.py | 7 ++++--- openerp/http.py | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/addons/website_form/controllers/main.py b/addons/website_form/controllers/main.py index be1bf5aa53a..1dddd28a23a 100644 --- a/addons/website_form/controllers/main.py +++ b/addons/website_form/controllers/main.py @@ -22,7 +22,7 @@ class WebsiteForm(http.Controller): return json.dumps(False) try: - data = self.extract_data(model_record, ** kwargs) + data = self.extract_data(model_record, request.params) # If we encounter an issue while extracting data except ValidationError, e: # I couldn't find a cleaner way to pass data to an exception @@ -101,7 +101,7 @@ class WebsiteForm(http.Controller): # Extract all data sent by the form and sort its on several properties - def extract_data(self, model, **kwargs): + def extract_data(self, model, values): data = { 'record': {}, # Values to create record @@ -112,7 +112,8 @@ class WebsiteForm(http.Controller): authorized_fields = model.sudo()._get_form_writable_fields() error_fields = [] - for field_name, field_value in kwargs.items(): + + for field_name, field_value in values.items(): # If the value of the field if a file if hasattr(field_value, 'filename'): # Undo file upload field name indexing diff --git a/openerp/http.py b/openerp/http.py index 73fd66fc087..63456607e18 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -770,9 +770,9 @@ class HttpRequest(WebRequest): def __init__(self, *args): super(HttpRequest, self).__init__(*args) - params = self.httprequest.args.to_dict() - params.update(self.httprequest.form.to_dict()) - params.update(self.httprequest.files.to_dict()) + params = collections.OrderedDict(self.httprequest.args) + params.update(self.httprequest.form) + params.update(self.httprequest.files) params.pop('session_id', None) self.params = params @@ -1617,6 +1617,7 @@ class Root(object): try: httprequest = werkzeug.wrappers.Request(environ) httprequest.app = self + httprequest.parameter_storage_class = werkzeug.datastructures.ImmutableOrderedMultiDict explicit_session = self.setup_session(httprequest) self.setup_db(httprequest)