Skip to content

Commit e32276f

Browse files
author
Tim Heap
committed
Keep composite field values after a validation error
Previously the submitted value for a composite field was lost if the form had a validation error. Fixes danni#18
1 parent b66d379 commit e32276f

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

postgres_composite_types/forms.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ def __init__(self, *args, fields=None, model=None, **kwargs):
109109
self.widget.widgets.values()):
110110
widget.attrs['placeholder'] = field.label
111111

112+
def prepare_value(self, value):
113+
"""
114+
Prepare the field data for the CompositeTypeWidget, which expects data
115+
as a dict.
116+
"""
117+
if isinstance(value, CompositeType):
118+
return value.__to_dict__()
119+
120+
return value
121+
112122
def validate(self, value):
113123
pass
114124

@@ -155,7 +165,9 @@ def get_bound_field(self, form, field_name):
155165

156166
class CompositeTypeWidget(forms.Widget):
157167
"""
158-
Takes an ordered dict of widgets to produce a composite form widget
168+
Takes an ordered dict of widgets to produce a composite form widget. This
169+
widget knows nothing about CompositeTypes, and works only with dicts for
170+
initial and output data.
159171
"""
160172
template_name = \
161173
'postgres_composite_types/forms/widgets/composite_type.html'
@@ -170,7 +182,7 @@ def __init__(self, widgets, **kwargs):
170182

171183
@property
172184
def is_hidden(self):
173-
return all(w.is_hidden for w in self.widgets)
185+
return all(w.is_hidden for w in self.widgets.values())
174186

175187
def get_context(self, name, value, attrs):
176188
context = super().get_context(name, value, attrs)
@@ -187,12 +199,9 @@ def get_context(self, name, value, attrs):
187199
if id_:
188200
widget_attrs['id'] = '%s-%s' % (id_, subname)
189201

190-
subwidgets[subname] = widget.render('%s-%s' % (name, subname),
191-
getattr(value, subname, None),
192-
final_attrs)
193202
widget_context = widget.get_context(
194203
'%s-%s' % (name, subname),
195-
getattr(value, subname, None),
204+
value.get(subname),
196205
widget_attrs)
197206
subwidgets[subname] = widget_context['widget']
198207

tests/test_forms.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ def test_validation(self):
5555
# Errors should be formatted like 'Label: Error message'
5656
self.assertEqual(str(form.errors['simple_field'][0]),
5757
'A number: Enter a whole number.')
58+
# Fields with validation errors should render with their invalid input
59+
self.assertHTMLEqual(
60+
str(form['simple_field']['a']),
61+
"""
62+
<input id="id_simple_field-a" name="simple_field-a"
63+
placeholder="A number" required type="number" value="one" />
64+
""")
5865

5966
def test_subfield_validation(self):
6067
"""Errors on subfields should be accessible"""

0 commit comments

Comments
 (0)