Forms
WORK IN PROGRESS
Just know that py4web.utils.form.Form
is a pretty much equivalent to
web2py’s SQLFORM
.
The Form
constructor accepts the following arguments:
Form(self,
table,
record=None,
readonly=False,
deletable=True,
formstyle=FormStyleDefault,
dbio=True,
keep_values=False,
form_name=False,
hidden=None,
before_validate=None):
Where:
table
: a DAL table or a list of fields (equivalent to old SQLFORM.factory)record
: a DAL record or record idreadonly
: set to True to make a readonly formdeletable
: set to False to disallow deletion of recordformstyle
: a function that renders the form using helpers (FormStyleDefault)dbio
: set to False to prevent any DB writeskeep_values
: if set to true, it remembers the values of the previously submitted formform_name
: the optional name of this formhidden
: a dictionary of hidden fields that is added to the formbefore_validate
: an optional validator.
Example
Here is a simple example of a custom form not using database access. We
declare an endpoint /form_example
, which will be used both for the
GET and for the POST of the form:
from py4web import Session, redirect, URL
from py4web.utils.dbstore import DBStore
from py4web.utils.form import Form, FormStyleBulma
db = DAL('sqlite:memory')
session = Session(storage=DBStore(db))
@action('form_example', method=['GET', 'POST'])
@action.uses('form_example.html', session)
def form_example():
form = Form([
Field('product_name'),
Field('product_quantity', 'integer')],
formstyle=FormStyleBulma)
if form.accepted:
# Do something with form.vars['product_name'] and form.vars['product_quantity']
redirect(URL('index'))
return dict(form=form)
The form can be displayed in the template simply using [[=form]]
.
Form validation
The validation of form input can be done in two ways. One can define
requires
attributes of Field
, or one can define explicitly a
validation function. To do the latter, we pass to validate
a
function that takes the form and returns a dictionary, mapping field
names to errors. If the dictionary is non-empty, the errors will be
displayed to the user, and no database I/O will take place.
Here is an example:
from py4web import Field
from py4web.utils.form import Form, FormStyleBulma
from pydal.validators import IS_INT_IN_RANGE
def check_nonnegative_quantity(form):
if not form.errors and form.vars['product_quantity'] % 2:
form.errors['product_quantity'] = T('The product quantity must be even')
@action('form_example', method=['GET', 'POST'])
@action.uses('form_example.html', session)
def form_example():
form = Form([
Field('product_name'),
Field('product_quantity', 'integer', requires=IS_INT_IN_RANGE(0,100))],
validation=check_nonnegative_quantity,
formstyle=FormStyleBulma)
if form.accepted:
# Do something with form.vars['product_name'] and form.vars['product_quantity']
redirect(URL('index'))
return dict(form=form)