form: sort keys on rendering a WidgetDict (#21786)

This commit is contained in:
Thomas NOËL 2018-02-12 03:27:06 +01:00
parent 41f35ff075
commit 999e5f7c1f
2 changed files with 27 additions and 2 deletions

View File

@ -517,3 +517,17 @@ def test_wcsextrastringwidget():
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12,34'})
assert widget.has_error()
def test_widgetdict_widget():
widget = WidgetDict('test', value={'a': None, 'b': None, 'c': None})
mock_form_submission(req, widget, {'test$element0key': 'a', 'test$element0value': 'value-a',
'test$element1key': 'c', 'test$element1value': 'value-c',
'test$element2key': 'b', 'test$element2value': 'value-b'})
assert widget.parse() == {'a': 'value-a', 'b': 'value-b', 'c': 'value-c'}
# on rendering, elements are ordered by their key name
html_frags = str(widget.render_content()).split()
assert (html_frags.index('name="test$element0key"') < # a
html_frags.index('name="test$element2key"') < # b
html_frags.index('name="test$element1key"')) # c

View File

@ -1304,16 +1304,27 @@ class WidgetDict(quixote.form.widget.WidgetDict):
def render_content(self):
r = TemplateIO(html=True)
lines = []
for name in self.element_names:
if name in ('add_element', 'added_elements'):
continue
key_widget = self.get_widget(name + 'key')
value_widget = self.get_widget(name + 'value')
lines.append({'key': key_widget, 'value': value_widget})
def sort_key(line):
if not isinstance(line['key'], StringWidget) or not line['key'].value:
return (1, None) # empty keys always at the end
return (0, line['key'].value)
lines.sort(key=sort_key)
for line in lines:
r += htmltext('<div class="dict-key">%s</div>'
'<div class="dict-separator">: </div>'
'<div class="dict-value">%s</div>') % (
key_widget.render(),
value_widget.render())
line['key'].render(),
line['value'].render())
r += htmltext('\n')
r += self.get_widget('add_element').render()
r += self.get_widget('added_elements').render()