There are multiple ways to handle this, including Javascript on the client side, manipulation of form.custom.widget, the web2py server-side DOM, and custom widgets. Note, when adding a class to an existing element on the server side, you can use the .add_class method, which intelligently handles cases where there is already an existing class.
At the form level, you can use the server-side DOM:
form.elements('textarea', replace=lambda el: el.add_class('form-control'))
The above affects only this particular form.
Another option is to create a custom widget, which works at the table level and therefore affects all forms based on the table:
def text_widget(field, value, text_class='form-control'):
return SQLFORM.widgets.text.widget(field, value).add_class(text_class)
db.define_table('mytable',
Field('myfield', 'text', widget=text_widget))
Finally, you could monkey patch the text widget directly, which would affect all text fields in all tables:
SQLFORM.widgets.text._class = 'text form-control'
Anthony