When using TurboGears, your controller methods get their arguments built from
the various GET, POST, and URL mechanisms provided by CherryPy. The only
downside is that all the arguments will be strings and you’d like them
converted to their normal Python datatype: numbers to int, dates to
datetime, etc.

This conversion functionality is provided by the FormEncode package and is
applied to your methods using the @validate() decorator. FormEncode
provides both validation and conversion as a single step, reasoning that you
frequently need to validate something before you can convert it or that you’ll
need to convert something before you can really validate it.

The @validate() decorator can evaluate both widget-based forms and the
standard CherryPy arguments. The @validate() decorator is not required in
order to use TurboGears. If you don’t put a @validate() decorator on your
method, you’ll simply have to do the string validation and conversion yourself.

where yourpkg.forms.a_form is an instance of a turbogears.widgets.Form
sub-class or a callable that returns such an instance. The callable will be
called for each request, so you can dynamically build forms depending on the
request context.

The widgets system will take care of building a schema to handle the data
conversions and you’ll wind up with the int or datetime objects you
specified when building the form. When paired with the error handling
decorators, you can handle the common case of building a form, validating it,
re-displaying the form if there are errors, and converting a valid form into the
proper arguments in only a few lines of Python.

When not using forms, the story gets a bit more complex. Basically, you need to
specify which validator goes with which argument using the validators
keyword argument for the validate decorator. Here’s a simple example:

As you can see FormEncode and TurboGears provide a number of useful validators
that are available in the turbogears.validators module.

For most validators, you can pass keyword arguments for more specific
constraints. For the list of available validators, check both the
FormEncode validators and TurboGears validators (source) modules.
You can also create your own validators or build on existing validators by
inheriting from one of the defaults. See the FormEncode documentation
for how this is done.

The dictionary passed to the validators argument of the validate
decorator maps the incoming field names to the appropriate FormEncode
validators - in this example, we used PlainText, OneOf and Money.
If all values pass validation, tg_errors won’t change from it’s default
value of None and you are assured that value will be an int.
Wait a minute! What’s this tg_errors?

If there’s a validation error, a dictionary named tg_errors will be passed
to the function, with keys for the field names that failed validation. If you
look up the keys, such as tg_errors['value'], you’ll find an Invalid
exception object. Invalid exception objects can be str()‘d if you’d like
to use them as user-friendly error messages or you can use the information
contained in them to handle the error as you like:

If you use form-based validation or if you pass a validation schema to the
validators argument (see below), the values in the tg_errors will
already be coerced into strings for your convenience. If you still need
access to the Invalid exception object thrown by the validation schema,
you can access it through cherrypy.request.validation_exception and
retrieve the Invalid exceptions for the individual fields that failed
validation through its error_dict attribute.

Note

If you omit the tg_errors=None keyword from the controller method’s
arguments, you get told that there is no error handler function. This is
a bit misleading as you don’t really need an error handler if you handle
things on your own, as explained here. See the documentation on
Error Handling for learning more about error handlers.

If you want to do multiple-field validation, reuse validators or just clean up
your code, validation Schema``sarethewaytogo.Youcreateavalidationschemabyinheritingfrom``turbogears.validators.Schema and pass the newly
created Schema as the validators argument instead of passing a
dictionary:

classMySchema(validators.Schema):pwd1=validators.String(not_empty=True)pwd2=validators.String(not_empty=True)chained_validators=[validators.FieldsMatch('pwd1','pwd2')]@expose()@validate(validators=MySchema())defpassword(self,pwd1,pwd2,tg_errors=None):iftg_errors:return"There was an error"return"Password ok!"

Besides noticing our brilliant security strategy, please notice the
chained_validators part of the schema that guarantees a pair of matching
fields.

Again, for information about Invalid exception objects, creating your
own validators, schema and FormEncode in general, refer to the FormEncode
Validator documentation and don’t be afraid to check the
formencode.validators source. It’s often more clear than the docs.

You can always use e.g. Python’s int() method to convert a string to an
integer and use a try/except block to catch errors in the conversion process:

fromturbogearsimportcontrollers,exposeclassRoot(controllers.RootController):@expose()defaddnum(self,x,y):"""Return the result of x+y."""try:returnstr(int(x)+int(y))exceptValueError:return"Input is not valid!"

This isn’t that hard, but it quickly becomes unwieldy when you start converting
large numbers of arguments. Moreover, you still have the problem of propagating
the errors back to your users. In the end, it’s usually far simpler to use the
validation framework.

Sometimes you need access to external and possibly dynamic information in your
validators, for example to change the outcome of the validation depending on this
information. The validate_python and _to_python methods of all validators
take an optional argument called state which is exactly for this purpose. The
value of this argument should be a turbogears.util.Bunch-like object (i.e. just
a simple data class that has arbitrary attributes) which provides the state
information for the validator (schema). See the FormEncode documentation about
‘state’ for more information.

The validate decorator function takes a keyword argument named state_factory
which expects a callable, which should return a Bunch object suitable to be passed
as the state parameter to the validator schema of the form widget.

Here’s a small example of how you can provide a validator with access to information
about the current request:

2) The validate decorator will only be called once per request. This can be a
problem if you call other exposed methods from another method.

The latter can be demonstrated with the following controller example snippet:

## BAD, DOES NOT WORK AS EXPECTED!@expose()@validate(validators=dict(userid=validators.String()))deffoo(self,userid=None,tg_errors=None):returnself.bar(userid=userid)@expose()@validate(validators=dict(userid=validators.Int()))defbar(self,userid=None,tg_errors=None):# userid is not validated if the call came from foo()returnuserid