I need to make a quantity range widget that renders like this, all on one line: FloatWidget "-" FloatWidget SingleSelectWidget Valid input would be: 100 - 1000 gallons 0.96 - barrels (second widget is None) - gallons (first two widgets are None, meaning no input) I'm implementing it this way: class QuantityRangeWidget(CompositeWidget): def __init__(self, name, **kwargs): options = [ (x, x, x) for x in VOLUME_UNITS + MASS_UNITS] widget.CompositeWidget.__init__(self, name, **kwargs) self.add(widget.FloatWidget, 'low') self.add(widget.FloatWidget, 'high') self.add(widget.SingleSelectWidget, 'unit', value='gallons', options=options) def render_content(self): tio = TemplateIO(html=True) tio += self.get_widget('low').render_content() tio += htmltext(" to ") tio += self.get_widget('high').render_content() tio += self.get_widget('unit').render_content() return tio.getvalue() Is this the right way to do it? Should my ._parse method set the value to a tuple of subvalues, and .set_value propagate the values to the subwidgets? Or should I ignore the widget value and have caller look at the subwidget values directly? "form.get_widget('quantity')['low']"? I suppose I can't do "form['quantity']['low']" ? What if I need several range controls on the same form? All the subwidgets will be in a flat namespace in the HTML. I'm getting subwidget names like 'release$low', so I guess that's being taken care of automatically somehow. def _parse(self): is_low = self['low'] is not None is_high = self['high'] is not None is_unit = self['unit'] is not None if is_high and not is_low: self.error = "Must provide low number." if (is_low or is_high) and not is_unit: self.error = "Must provide unit." I made a date widget earlier but that was pretty straightforward, since the value is a datetime object, and I put the subwidgets in .year, .month, and .day attributes. (Perhaps I should have used .add() and .widgets, but I bypassed them.) But a range object doesn't have an obvious single value unless I arbitrarily say ".value = (low, high, unit)". Is that how to do it with composite widgets? After that I need to make a latitude/longitude widget that accepts: 123.45 West (degrees) 123 45.67 West (degrees, minutes) 123 45 45.67 West (degrees, minutes, seconds) But first I have to get the simpler widget down. What is the purpose of WidgetList and WidgetDict? At first I thought they were for making arbitrary composite widgets, but that raises the question of when to use them and when to use CompositeWidget directly, and what that funny 'add_element' widget is for. Then I thought, "No, they are specialized widgets, for growable lists/dicts." Are they for when you have multiple values and want to let the user as many additional values as they want? But there's nothing to delete an element if they want to go the other way. Or are these widgets for something else? -- -- Mike Orr