@view_config(renderer='templates/form.pt', name='widget_adapter')
@demonstrate('Widget Adapter')
def widget_adapter(self):
# Formish allows you to pair a widget against a type that
# doesn't "natively" lend itself to being representible by the
# widget; for example, it allows you to use a text area widget
# against a sequence type. To provide this feature, Formish
# uses an adapter to convert the sequence data to text during
# serialization and from text back to a sequence during
# deserialization.
#
# Deform doesn't have such a feature out of the box. This is
# on purpose: the feature is really too complicated and
# magical for civilians. However, if you really want or need
# it, you can add yourself as necessary using an adapter
# pattern.
#
# In the demo method below, we adapt a "normal" text area
# widget for use against a sequence. The resulting browser UI
# is the same as if we had used a TextAreaCSVWidget against
# the sequence as in the "textareacsv" test method.
#
# N.B.: we haven't automated the lookup of the widget adapter
# based on the type of the field and the type of the widget.
# Instead, we just construct an adapter manually. Adding an
# abstraction to the lookup based on the widget and schema
# types being adapted is easy enough, but trying to follow the
# codepath of the abstraction becomes brainbending.
# Therefore, we don't bother to show it.
class Row(colander.TupleSchema):
first = colander.SchemaNode(colander.Integer())
second = colander.SchemaNode(colander.String())
third = colander.SchemaNode(colander.Decimal())
class Rows(colander.SequenceSchema):
row = Row()
class Schema(colander.Schema):
csv = Rows()
schema = Schema()
form = deform.Form(schema, buttons=('submit',))
inner_widget = deform.widget.TextAreaWidget(rows=10, cols=60)
widget = SequenceToTextWidgetAdapter(inner_widget)
form['csv'].widget = widget
appstruct = {'csv':[ (1, 'hello', 4.5), (2, 'goodbye', 5.5) ]}
return self.render_form(form, appstruct=appstruct)