From 86e9031b6c1bf768fd53cf63d6e2932077e5ec07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Thu, 17 Sep 2015 11:11:14 +0200 Subject: [PATCH] fields: feed "live" formdata as variables when evaluating conditions (#8272) --- tests/test_form_pages.py | 32 ++++++++++++++++++++++++++++++++ wcs/fields.py | 25 +++++++++++++++---------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py index 586d44f..c564899 100644 --- a/tests/test_form_pages.py +++ b/tests/test_form_pages.py @@ -344,6 +344,38 @@ def test_form_multi_page_condition_data_source(pub): resp = resp.forms[0].submit('submit') # should go to second page assert 'f3' in resp.forms[0].fields +def test_form_multi_page_condition_data_source_with_form_variable(pub): + # this tries to recreate #8272 which is about a json datasource being + # used in a page condition and taking a value from the given page to + # filter its content. It is emulated here with a Python datasource + # being empty if a field was not set. + formdef = create_formdef() + formdef.fields = [fields.PageField(id='0', label='1st page', type='page'), + fields.StringField(id='1', label='string', varname='xxx', + required=False), + fields.PageField(id='2', label='2nd page', type='page', + condition='len(data_source.foobar) > 0'), + fields.StringField(id='3', label='string 2')] + formdef.store() + + # add the named data source, related to a field on the first page + NamedDataSource.wipe() + data_source = NamedDataSource(name='foobar') + data_source.data_source = {'type': 'formula', 'value': 'form_var_xxx and [form_var_xxx] or []'} + data_source.store() + + resp = get_app(pub).get('/test/') + formdef.data_class().wipe() + resp = resp.forms[0].submit('submit') # should go straight to validation + assert 'Check values then click submit.' in resp.body + assert resp.forms[0]['previous'] + resp = resp.forms[0].submit('previous') + + resp = get_app(pub).get('/test/') + resp.forms[0]['f1'] = 'HELLO' + resp = resp.forms[0].submit('submit') # should go to second page + assert 'f3' in resp.forms[0].fields + def test_form_submit_with_user(pub): create_user(pub) formdef = create_formdef() diff --git a/wcs/fields.py b/wcs/fields.py index 9705279..fbde7d3 100644 --- a/wcs/fields.py +++ b/wcs/fields.py @@ -1177,19 +1177,24 @@ class PageField(Field): if not self.condition: return True + # create variables with values currently being evaluated, not yet + # available in the formdata, keep them as var_xxx for compatibility, + # and add them as form_var_xxx. from formdata import get_dict_with_varnames + live_data = get_dict_with_varnames(formdef.fields, dict) + for k, v in live_data.items(): + live_data['form_' + k] = v + + # and feed those new variables in the global substitution system, they + # will shadow formdata context variables with their new "live" value, + # this may be useful when evaluating data sources. + class ConditionVars(object): + def get_substitution_variables(self): + return live_data + + get_publisher().substitutions.feed(ConditionVars()) data = get_publisher().substitutions.get_context_variables() - # create variables with values currently being evaluated, not yet - # available in the formdata - dict_with_varnames = get_dict_with_varnames(formdef.fields, dict) - # add them as var_xxx for compatibility - data.update(dict_with_varnames) - # and add them as form_var_xxx, overriding context variables with their - # "live" value - for k, v in dict_with_varnames.items(): - data['form_' + k] = v - try: if eval(self.condition, get_publisher().get_global_eval_dict(), data): return True -- 2.5.1