Fields are referenced by their HTML element name. Whenever a field is defined within a form any additional keyword arguments are used as attributes on the element itself. Current fields that are included are:

Field

Output

Input

<input type=”” />

Button

<button></button>

Textarea

<textarea></textarea>

Select

<select></select>

There are also a bunch of convenience classes as well which may add additional validators and filters to the field.

When is_valid() is called the POST’d data will be injected directly into the User object. While this is great for simple CRUD interfaces, things can get more complex when an object contains other objects. To resolve this we have to define a mapping to map the flat post data to the various objects (we only need to define the mapping for data that isn’t a direct mapping).

A basic mapping consists of a dict of key/value pairs where the value is a tuple that denotes the object ‘tree’.

mapping={'field_name':('attribute','attribute','attribute')}

We’ll take the same example from above, but modify it slightly so that our User object now also contains a Contact object (note that some of this code such as the entities would be handled automatically by your ORM of choice).

Filters and validators allow you to sanitize and modify your data prior to being used within your application. By default, all fields have the Trim filter which removes whitespace from the value of the field.

When the is_valid() method is called on the form each field is filtered, and then validated.

To add new validators and filters to a field you simply add them as a keyword argument to the field definition.

fromwatsonimportformfromwatson.formimportfieldsfromwatsonimportvalidatorsclassLogin(form.Form):username=fields.Text(label='Username',validators=[validators.Length(min=10)])password=fields.Password(label='Password',validators=[validators.Required()])# required can actually be set via required=Truesubmit=fields.Submit(value='Login',button_mode=True)

For a full list of validators and filters check out filters and validators in the reference library.

Validating forms is usually done within a controller. We’ll utilize the Login form above to demonstrate this...

fromwatson.frameworkimportcontrollersfromappimportformsclassLogin(controllers.Rest):defGET(self):form=forms.Login('login_form',action='/login')form.data=self.redirect_vars# populate the form with POST'd data to avoid the PRG issue# we don't really need to do thisreturn{'form':form}defPOST(self):form=forms.Login('login_form')form.data=self.request.postifform.is_valid():self.flash_messages.add('Successfully logged in')self.redirect('home')else:self.redirect('login')

With the above code, when a user hits /login, they are presented with a login form from the GET method of the controller. As they submit the form, the code within the POST method will execute. If the form is valid, then they will be redirected to whatever the ‘home’ route displays, otherwise they will be redirected back to the GET method again.

The above code will automatically add a new field (named csrf_token) to the form, which then will need to be rendered in your view. You will also need to pass the session into the form when it is instantiated so that the csrf token can be saved against the form.