From 0d5aafcf48cd5e6c13aa118add55a01e3c81ff6a Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 5 Apr 2019 12:00:05 +0200 Subject: [PATCH 2/2] api: store display/structured on submit of an item field with raw id (#32013) --- tests/test_api.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++ wcs/api.py | 20 ++++++++++++---- 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index ecdd03cd..e5193c14 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -2355,3 +2355,64 @@ def test_reverse_geocoding(pub): pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')) resp = get_app(pub).get('/api/reverse-geocoding?lat=0&lon=0') assert urlopen.call_args[0][0] == 'http://reverse.example.net/?param=value&format=json&addressdetails=1&lat=0&lon=0&accept-language=en' + + +def test_formdef_submit_structured(pub, local_user): + Role.wipe() + role = Role(name='test') + role.store() + local_user.roles = [role.id] + local_user.store() + + FormDef.wipe() + formdef = FormDef() + formdef.name = 'test' + formdef.fields = [ + fields.ItemField(id='0', label='foobar', varname='foobar', + data_source={ + 'type': 'json', + 'value': 'http://datasource.com', + }), + fields.ItemField(id='1', label='foobar1', varname='foobar1', + data_source={ + 'type': 'formula', + 'value': '[dict(id=i, text=\'label %s\' % i, foo=i) for i in range(10)]', + }), + ] + formdef.store() + data_class = formdef.data_class() + + def url(): + signed_url = sign_url( + 'http://example.net/api/formdefs/test/submit' + '?format=json&orig=coucou&email=%s' % urllib.quote(local_user.email), '1234') + return signed_url[len('http://example.net'):] + + with mock.patch('qommon.misc.urlopen') as urlopen: + urlopen.side_effect = lambda *args: StringIO('''\ +{"data": [{"id": 0, "text": "zéro", "foo": "bar"}, \ +{"id": 1, "text": "uné", "foo": "bar1"}, \ +{"id": 2, "text": "deux", "foo": "bar2"}]}''') + resp = get_app(pub).post_json(url(), {'data': { + '0': '0', + "1": '3', + }}) + + formdata = data_class.get(resp.json['data']['id']) + assert formdata.status == 'wf-new' + assert formdata.data['0'] == '0' + assert formdata.data['0_display'] == 'zéro' + assert formdata.data['0_structured'] == { + 'id': 0, + 'text': 'zéro', + 'foo': 'bar', + } + assert formdata.data['1'] == '3' + assert formdata.data['1_display'] == 'label 3' + assert formdata.data['1_structured'] == { + 'id': 3, + 'text': 'label 3', + 'foo': 3, + } + + data_class.wipe() diff --git a/wcs/api.py b/wcs/api.py index 3bce0974..dc75e23e 100644 --- a/wcs/api.py +++ b/wcs/api.py @@ -61,14 +61,24 @@ def posted_json_data_to_formdata_data(formdef, data): if field.store_structured_value and structured in data: data['%s_structured' % field.id] = data.pop(structured) - # parse special fields + # complete/adapt field values for field in formdef.get_all_fields(): - if not hasattr(field, 'from_json_value'): - continue + structured = '%s_structured' % field.id + display = '%s_display' % field.id if data.get(field.id) is None: continue - data[field.id] = field.from_json_value(data[field.id]) - + # only fill display/structured if both are absent + if display not in data and structured not in data: + if field.store_display_value: + display_value = field.store_display_value(data, field.id) + if display_value is not None: + data[display] = display_value + if field.store_structured_value: + structured_value = field.store_structured_value(data, field.id) + if structured_value is not None: + data[structured] = structured_value + if hasattr(field, 'from_json_value'): + data[field.id] = field.from_json_value(data[field.id]) return data -- 2.20.1