From 90b1d4ec9e31ee1919c5a7edf722d7886273b53d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 13 Nov 2020 09:44:24 +0100
Subject: [PATCH 2/2] workflow: prefix fields in FormWorkflowStatusItem
 (#13846)

---
 tests/backoffice_pages/test_all.py |  64 ++++++++---------
 tests/form_pages/test_all.py       | 106 ++++++++++++++---------------
 tests/form_pages/test_block.py     |   2 +-
 tests/form_pages/test_formdata.py  |  65 +++++++++++++++---
 tests/test_workflows.py            |   4 +-
 wcs/fields.py                      |   1 -
 wcs/wf/form.py                     |   9 ++-
 7 files changed, 151 insertions(+), 100 deletions(-)

diff --git a/tests/backoffice_pages/test_all.py b/tests/backoffice_pages/test_all.py
index 8a3cf1e4..941e6d02 100644
--- a/tests/backoffice_pages/test_all.py
+++ b/tests/backoffice_pages/test_all.py
@@ -3654,13 +3654,13 @@ def test_backoffice_workflow_display_form(pub):
             break
     app = login(get_app(pub))
     resp = app.get(formdata.get_url(backoffice=True))
-    assert 'f1' in resp.form.fields
-    resp.form['f1'] = 'blah'
+    assert 'fblah_1' in resp.form.fields
+    resp.form['fblah_1'] = 'blah'
     # don't fill required radio button
     resp = resp.form.submit('submit')
     assert formdef.data_class().get(formdata.id).status == 'wf-new'
     assert 'There were errors processing your form.' in resp.text
-    resp.form['f2'] = 'c'
+    resp.form['fblah_2'] = 'c'
     resp = resp.form.submit('submit')
     assert formdef.data_class().get(formdata.id).status == 'wf-accepted'
     assert formdef.data_class().get(formdata.id).workflow_data == {
@@ -3704,8 +3704,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
             break
     app = login(get_app(pub))
     resp = app.get(formdata.get_url(backoffice=True))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
 
     # check with static condition
     display_form.formdef.fields = [
@@ -3717,8 +3717,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
-    assert 'f1' in resp.form.fields
-    assert 'f2' not in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' not in resp.form.fields
 
     # check condition based on formdata
     display_form.formdef.fields = [
@@ -3730,8 +3730,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
 
     display_form.formdef.fields = [
             fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
@@ -3742,8 +3742,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
 
     # check with live conditions
     display_form.formdef.fields = [
@@ -3755,30 +3755,30 @@ def test_backoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
-    assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
-    assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
+    assert resp.html.find('div', {'data-field-id': 'blah_1'}).attrs['data-live-source'] == 'true'
+    assert resp.html.find('div', {'data-field-id': 'blah_2'}).attrs.get('style') == 'display: none'
     live_url = resp.html.find('form').attrs['data-live-url']
     assert '/backoffice/' in live_url
-    resp.form['f1'] = ''
+    resp.form['fblah_1'] = ''
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert not live_resp.json['result']['2']['visible']
+    assert live_resp.json['result']['blah_1']['visible']
+    assert not live_resp.json['result']['blah_2']['visible']
 
-    resp.form['f1'] = 'xxx'
+    resp.form['fblah_1'] = 'xxx'
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert live_resp.json['result']['2']['visible']
+    assert live_resp.json['result']['blah_1']['visible']
+    assert live_resp.json['result']['blah_2']['visible']
 
     # check submit doesn't work
     resp = resp.form.submit('submit')
     assert 'There were errors processing your form.' in resp.text
 
-    resp.form['f1'] = 'xxx2'
+    resp.form['fblah_1'] = 'xxx2'
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert not live_resp.json['result']['2']['visible']
+    assert live_resp.json['result']['blah_1']['visible']
+    assert not live_resp.json['result']['blah_2']['visible']
 
     # check submit does work when second field is hidden
     resp = resp.form.submit('submit').follow()
@@ -3832,14 +3832,14 @@ def test_backoffice_workflow_form_with_live_data_source(pub):
         urlopen.side_effect = side_effect
 
         resp = login(app).get(formdata.get_url(backoffice=True))
-        assert 'f1' in resp.form.fields
-        assert 'f2' in resp.form.fields
-        assert resp.form.fields['f2'][0].options == [(u'A', False, u'hello'), (u'B', False, u'world')]
+        assert 'fblah_1' in resp.form.fields
+        assert 'fblah_2' in resp.form.fields
+        assert resp.form.fields['fblah_2'][0].options == [(u'A', False, u'hello'), (u'B', False, u'world')]
 
         live_url = resp.html.find('form').attrs['data-live-url']
-        resp.form['f1'] = 'toto'
-        live_resp = app.post(live_url + '?modified_field_id=1', params=resp.form.submit_fields())
-        assert live_resp.json['result']['2']['items'] == [{u'text': u'hello', u'id': u'C'}, {u'text': u'world', u'id': u'D'}]
+        resp.form['fblah_1'] = 'toto'
+        live_resp = app.post(live_url + '?modified_field_id=blah_1', params=resp.form.submit_fields())
+        assert live_resp.json['result']['blah_2']['items'] == [{u'text': u'hello', u'id': u'C'}, {u'text': u'world', u'id': u'D'}]
 
 
 def test_backoffice_criticality_in_formdef_listing(pub):
@@ -5211,8 +5211,8 @@ def test_lazy_eval_with_conditional_workflow_form(pub):
     formdata.store()
 
     resp = app.get(formdata.get_url(backoffice=True))
-    resp.forms[0]['f1'] = 'a'
-    resp.forms[0]['f2'] = 'b'
+    resp.forms[0]['flocal_1'] = 'a'
+    resp.forms[0]['flocal_2'] = 'b'
     resp = resp.forms[0].submit()
     assert formdata.select()[0].status == 'wf-done'
 
diff --git a/tests/form_pages/test_all.py b/tests/form_pages/test_all.py
index 0e87413d..8d5f8444 100644
--- a/tests/form_pages/test_all.py
+++ b/tests/form_pages/test_all.py
@@ -5893,7 +5893,7 @@ def test_user_global_action_along_form(pub):
     formdata = formdef.data_class().select()[0]
 
     resp = app.get(formdata.get_url())
-    assert resp.form['f1'].attrs['aria-required'] == 'true'
+    assert resp.form['fxxx_1'].attrs['aria-required'] == 'true'
     assert 'button-action-1' in resp.form.fields
     resp = resp.form.submit('button-action-1')
 
@@ -6497,35 +6497,35 @@ def test_field_live_select_content_on_workflow_form(pub, http_requests):
     assert 'The form has been recorded' in resp.text
 
     assert 'data-live-url' in resp.html.find('form').attrs
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
-    assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
-    assert resp.html.find('div', {'data-field-id': '3'}).find('select')
+    assert 'fxxx_1' in resp.form.fields
+    assert 'fxxx_2' in resp.form.fields
+    assert resp.html.find('div', {'data-field-id': 'xxx_2'}).attrs['data-live-source'] == 'true'
+    assert resp.html.find('div', {'data-field-id': 'xxx_3'}).find('select')
     resp = resp.form.submit('submit')  # submit with error, to check <form> attributes
     assert 'data-live-url' in resp.html.find('form').attrs
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
-    assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
-    assert resp.html.find('div', {'data-field-id': '3'}).find('select')
-    resp.form['f1'] = 'hello'
+    assert 'fxxx_1' in resp.form.fields
+    assert 'fxxx_2' in resp.form.fields
+    assert resp.html.find('div', {'data-field-id': 'xxx_2'}).attrs['data-live-source'] == 'true'
+    assert resp.html.find('div', {'data-field-id': 'xxx_3'}).find('select')
+    resp.form['fxxx_1'] = 'hello'
     live_resp = app.post('/test/1/live', params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert live_resp.json['result']['2']['visible']
-    assert live_resp.json['result']['3']['visible']
-    assert not 'items' in live_resp.json['result']['3']
-    resp.form['f2'] = 'plop'
-    live_resp = app.post('/test/1/live?modified_field_id=2', params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert live_resp.json['result']['2']['visible']
-    assert live_resp.json['result']['3']['visible']
-    assert 'items' in live_resp.json['result']['3']
-    assert len(live_resp.json['result']['3']['items']) > 0
-
-    resp.form['f3'].options = []
-    for item in live_resp.json['result']['3']['items']:
+    assert live_resp.json['result']['xxx_1']['visible']
+    assert live_resp.json['result']['xxx_2']['visible']
+    assert live_resp.json['result']['xxx_3']['visible']
+    assert not 'items' in live_resp.json['result']['xxx_3']
+    resp.form['fxxx_2'] = 'plop'
+    live_resp = app.post('/test/1/live?modified_field_id=xxx_2', params=resp.form.submit_fields())
+    assert live_resp.json['result']['xxx_1']['visible']
+    assert live_resp.json['result']['xxx_2']['visible']
+    assert live_resp.json['result']['xxx_3']['visible']
+    assert 'items' in live_resp.json['result']['xxx_3']
+    assert len(live_resp.json['result']['xxx_3']['items']) > 0
+
+    resp.form['fxxx_3'].options = []
+    for item in live_resp.json['result']['xxx_3']['items']:
         # simulate javascript filling the <select>
-        resp.form['f3'].options.append((item['id'], False, item['text']))
-    resp.form['f3'] = 'a'
+        resp.form['fxxx_3'].options.append((item['id'], False, item['text']))
+    resp.form['fxxx_3'] = 'a'
 
     resp = resp.form.submit('submit')
     assert 'invalid value selected' not in resp
@@ -7049,8 +7049,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
 
     app = login(get_app(pub), username='foo', password='foo')
     resp = app.get(formdata.get_url(backoffice=False))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
 
     # check with static condition
     display_form.formdef.fields = [
@@ -7062,8 +7062,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
-    assert 'f1' in resp.form.fields
-    assert 'f2' not in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' not in resp.form.fields
 
     # check condition based on formdata
     display_form.formdef.fields = [
@@ -7075,8 +7075,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
 
     display_form.formdef.fields = [
             fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
@@ -7087,8 +7087,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
 
     # check with live conditions
     display_form.formdef.fields = [
@@ -7100,29 +7100,29 @@ def test_frontoffice_workflow_form_with_conditions(pub):
     wf.store()
 
     resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
-    assert 'f1' in resp.form.fields
-    assert 'f2' in resp.form.fields
-    assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
-    assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
+    assert 'fblah_1' in resp.form.fields
+    assert 'fblah_2' in resp.form.fields
+    assert resp.html.find('div', {'data-field-id': 'blah_1'}).attrs['data-live-source'] == 'true'
+    assert resp.html.find('div', {'data-field-id': 'blah_2'}).attrs.get('style') == 'display: none'
     live_url = resp.html.find('form').attrs['data-live-url']
-    resp.form['f1'] = ''
+    resp.form['fblah_1'] = ''
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert not live_resp.json['result']['2']['visible']
+    assert live_resp.json['result']['blah_1']['visible']
+    assert not live_resp.json['result']['blah_2']['visible']
 
-    resp.form['f1'] = 'xxx'
+    resp.form['fblah_1'] = 'xxx'
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert live_resp.json['result']['2']['visible']
+    assert live_resp.json['result']['blah_1']['visible']
+    assert live_resp.json['result']['blah_2']['visible']
 
     # check submit doesn't work
     resp = resp.form.submit('submit')
     assert 'There were errors processing your form.' in resp.text
 
-    resp.form['f1'] = 'xxx2'
+    resp.form['fblah_1'] = 'xxx2'
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['1']['visible']
-    assert not live_resp.json['result']['2']['visible']
+    assert live_resp.json['result']['blah_1']['visible']
+    assert not live_resp.json['result']['blah_2']['visible']
 
     # check submit does work when second field is hidden
     resp = resp.form.submit('submit').follow()
@@ -7166,13 +7166,13 @@ def test_frontoffice_workflow_form_with_dynamic_comment(pub):
 
     app = login(get_app(pub), username='foo', password='foo')
     resp = app.get(formdata.get_url(backoffice=False))
-    assert 'f1' in resp.form.fields
+    assert 'fblah_1' in resp.form.fields
 
     live_url = resp.html.find('form').attrs['data-live-url']
-    resp.form['f1'] = 'test'
+    resp.form['fblah_1'] = 'test'
     live_resp = app.post(live_url, params=resp.form.submit_fields())
-    assert live_resp.json['result']['2']['visible']
-    assert live_resp.json['result']['2']['content'] == '<p>value is test</p>'
+    assert live_resp.json['result']['blah_2']['visible']
+    assert live_resp.json['result']['blah_2']['content'] == '<p>value is test</p>'
 
 
 def test_frontoffice_workflow_form_with_impossible_condition(pub):
@@ -7212,8 +7212,8 @@ def test_frontoffice_workflow_form_with_impossible_condition(pub):
 
     app = login(get_app(pub), username='foo', password='foo')
     resp = app.get(formdata.get_url(backoffice=False))
-    assert 'f1' not in resp.form.fields
-    assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
+    assert 'fblah_1' not in resp.form.fields
+    assert resp.html.find('div', {'data-field-id': 'blah_2'}).attrs.get('style') == 'display: none'
 
 
 def test_choice_button_ignore_form_errors(pub):
diff --git a/tests/form_pages/test_block.py b/tests/form_pages/test_block.py
index e9de3ed0..cb64a826 100644
--- a/tests/form_pages/test_block.py
+++ b/tests/form_pages/test_block.py
@@ -412,7 +412,7 @@ def test_workflow_form_block_prefill(pub):
     resp = resp.form.submit('submit')  # -> validation
     resp = resp.form.submit('submit').follow()
     assert 'The form has been recorded' in resp
-    assert resp.form['f3$element0$f123'].value == 'foo@localhost'
+    assert resp.form['fxxx_3$element0$f123'].value == 'foo@localhost'
 
 
 def test_block_title_and_comment(pub, blocks_feature):
diff --git a/tests/form_pages/test_formdata.py b/tests/form_pages/test_formdata.py
index 33f7c85f..2a42b812 100644
--- a/tests/form_pages/test_formdata.py
+++ b/tests/form_pages/test_formdata.py
@@ -1037,7 +1037,7 @@ def test_formdata_form_file_download(pub):
     assert 'The form has been recorded' in resp.text
 
     assert 'qommon.fileupload.js' in resp.text
-    resp.forms[0]['f1$file'] = Upload('test.txt', b'foobar', 'text/plain')
+    resp.forms[0]['fxxx_1$file'] = Upload('test.txt', b'foobar', 'text/plain')
     resp = resp.forms[0].submit('submit')
 
     assert formdef.data_class().count() == 1
@@ -1086,7 +1086,7 @@ def test_formdata_workflow_form_prefill(pub):
     assert resp.status_int == 302
     resp = resp.follow()
     assert 'The form has been recorded' in resp.text
-    assert resp.forms[0]['f1'].value == 'foo@localhost'
+    assert resp.forms[0]['fxxx_1'].value == 'foo@localhost'
 
 
 def test_formdata_workflow_form_prefill_conditional_field(pub):
@@ -1127,7 +1127,7 @@ def test_formdata_workflow_form_prefill_conditional_field(pub):
     assert resp.status_int == 302
     resp = resp.follow()
     assert 'The form has been recorded' in resp.text
-    assert resp.forms[0]['f2'].value == 'foo@localhost'
+    assert resp.forms[0]['fxxx_2'].value == 'foo@localhost'
 
 
 def test_formdata_workflow_form_prefill_checkbox(pub):
@@ -1164,9 +1164,9 @@ def test_formdata_workflow_form_prefill_checkbox(pub):
     assert 'Check values then click submit.' in resp
     resp = resp.form.submit('submit').follow()
     assert 'The form has been recorded' in resp
-    assert resp.form['f1'].checked is True
-    assert resp.form['f2'].checked is True
-    resp.form['f1'].checked = False
+    assert resp.form['fxxx_1'].checked is True
+    assert resp.form['fxxx_2'].checked is True
+    resp.form['fxxx_1'].checked = False
     resp = resp.form.submit('submit')
 
     formdata = formdef.data_class().select()[0]
@@ -1242,13 +1242,58 @@ def test_formdata_workflow_form_prefill_autocomplete(pub):
         assert 'The form has been recorded' in resp
 
         # check display value is in form action widget
-        assert resp.form['f4'].attrs['data-value'] == '1'
-        assert resp.form['f4'].attrs['data-initial-display-value'] == 'hello'
+        assert resp.form['fxxx_4'].attrs['data-value'] == '1'
+        assert resp.form['fxxx_4'].attrs['data-initial-display-value'] == 'hello'
 
         # check it is also displayed in a fresh session
         resp = login(get_app(pub), username='foo', password='foo').get(resp.request.url)
-        assert resp.form['f4'].attrs['data-value'] == '1'
-        assert resp.form['f4'].attrs['data-initial-display-value'] == 'hello'
+        assert resp.form['fxxx_4'].attrs['data-value'] == '1'
+        assert resp.form['fxxx_4'].attrs['data-initial-display-value'] == 'hello'
+
+
+def test_formdata_workflow_many_forms(pub):
+    create_user(pub)
+    wf = Workflow(name='status')
+    st1 = wf.add_status('Status1', 'st1')
+
+    display_form1 = FormWorkflowStatusItem()
+    display_form1.id = '_x'
+    display_form1.by = ['_submitter']
+    display_form1.varname = 'xxx'
+    display_form1.formdef = WorkflowFormFieldsFormDef(item=display_form1)
+    display_form1.formdef.fields.append(fields.StringField(id='1', label='blah1'))
+    st1.items.append(display_form1)
+    display_form1.parent = st1
+
+    display_form2 = FormWorkflowStatusItem()
+    display_form2.id = '_y'
+    display_form2.by = ['_submitter']
+    display_form2.varname = 'yyy'
+    display_form2.formdef = WorkflowFormFieldsFormDef(item=display_form2)
+    display_form2.formdef.fields.append(fields.StringField(id='1', label='blah2'))
+    st1.items.append(display_form2)
+    display_form2.parent = st1
+
+    wf.store()
+
+    FormDef.wipe()
+    formdef = FormDef()
+    formdef.name = 'test'
+    formdef.workflow_id = wf.id
+    formdef.fields = []
+    formdef.store()
+    formdef.data_class().wipe()
+
+    resp = login(get_app(pub), username='foo', password='foo').get('/test/')
+    resp = resp.forms[0].submit('submit')
+    assert 'Check values then click submit.' in resp.text
+    resp = resp.forms[0].submit('submit')
+    assert resp.status_int == 302
+    resp = resp.follow()
+    assert 'The form has been recorded' in resp.text
+    assert 'fxxx_1' in resp.form.fields
+    assert 'fyyy_1' in resp.form.fields
+    assert 'submit' in resp.form.fields
 
 
 def test_formdata_named_wscall(http_requests, pub):
diff --git a/tests/test_workflows.py b/tests/test_workflows.py
index d4a5c0b1..325fd412 100644
--- a/tests/test_workflows.py
+++ b/tests/test_workflows.py
@@ -2413,7 +2413,7 @@ def test_display_form(two_pubs):
     assert form.widgets[1].title == 'Date'
 
     two_pubs.get_request().environ['REQUEST_METHOD'] = 'POST'
-    two_pubs.get_request().form = {'f1': 'Foobar', 'f2': '2015-05-12', 'submit': 'submit'}
+    two_pubs.get_request().form = {'fxxx_1': 'Foobar', 'fxxx_2': '2015-05-12', 'submit': 'submit'}
     display_form.submit_form(form, formdata, None, None)
 
     assert formdata.get_substitution_variables()['xxx_var_date'] == '2015-05-12'
@@ -2426,7 +2426,7 @@ def test_display_form(two_pubs):
     form = Form(action='#', use_tokens=False)
     display_form.fill_form(form, formdata, None)
     two_pubs.get_request().environ['REQUEST_METHOD'] = 'POST'
-    two_pubs.get_request().form = {'f1': 'Foobar', 'f2': '12/05/2015', 'submit': 'submit'}
+    two_pubs.get_request().form = {'fxxx_1': 'Foobar', 'fxxx_2': '12/05/2015', 'submit': 'submit'}
     display_form.submit_form(form, formdata, None, None)
     assert formdata.get_substitution_variables()['xxx_var_date'] == '12/05/2015'
 
diff --git a/wcs/fields.py b/wcs/fields.py
index 0b467d46..24b320d8 100644
--- a/wcs/fields.py
+++ b/wcs/fields.py
@@ -546,7 +546,6 @@ class WidgetField(Field):
     def perform_more_widget_changes(self, form, kwargs, edit = True):
         pass
 
-
     def add_to_view_form(self, form, value = None):
         kwargs = {'render_br': False}
 
diff --git a/wcs/wf/form.py b/wcs/wf/form.py
index bc239f92..760d41f8 100644
--- a/wcs/wf/form.py
+++ b/wcs/wf/form.py
@@ -168,9 +168,16 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
     def fill_form(self, form, formdata, user, displayed_fields=None, **kwargs):
         if not self.formdef:
             return
+        for field in self.formdef.fields:
+            try:
+                field.id = '%s_%s' % (self.varname, int(field.id))
+            except ValueError:
+                # already prefixed
+                pass
         self.formdef.var_prefix = self.varname
         self.formdef.add_fields_to_form(form, displayed_fields=displayed_fields)
-        form.add_submit('submit', _('Submit'))
+        if 'submit' not in form._names:
+            form.add_submit('submit', _('Submit'))
 
         # put varname in a form attribute so it can be used in templates to
         # identify the form.
-- 
2.28.0

