User interaction¶
Forms and Inputs¶
Form
s get input from users. Build up the Form
by adding Input
Widget
s to it (or one of its children), via an appropriate FormLayout
.
To group some TextInput
s visually, add them to FieldSet
via a
FormLayout
. The FormLayout
arranges the TextInput
s with their
associated labels and validation error messages. Call
add_child()
to add the FieldSet
to the
Form
.
class AddressForm(Form):
def __init__(self, view):
super().__init__(view, 'address_form')
inputs = self.add_child(FieldSet(view, legend_text='Add an address'))
inputs.use_layout(FormLayout())
new_address = Address()
inputs.layout.add_input(TextInput(self, new_address.fields.name))
inputs.layout.add_input(TextInput(self, new_address.fields.email_address))
Fields provide metadata¶
Each Input
is wired to an associated Field
. A Field
holds more information about the similarly named attribute of the
Address. EmailField
constrains the input to be a valid email
address. Invalid input is blocked by the EmailField
and the
FormLayout
displays an error message underneath its TextInput
.
Field
s are defined on Address using a ExposedNames
namespace:
class Address(Base):
__tablename__ = 'addressbook2_address'
id = Column(Integer, primary_key=True)
email_address = Column(UnicodeText)
name = Column(UnicodeText)
fields = ExposedNames()
fields.name = lambda i: Field(label='Name', required=True)
fields.email_address = lambda i: EmailField(label='Email', required=True)
Note
Don’t confuse Field
s with SQLAlchemy’s Columns.
The email_address Field
sets the email_address attribute of an
Address when a Form
is submitted (and after validating the
input). A Column on that same email_address takes another
step—to persist the attribute to the database. They are
independent and do not have to be used together.