Write Your Controller Methods

Turboegars use CherryPy as default controller and web server. See the CherryPy documentation for help with structuring your controllers:

Debug your controller

You’ve learn the controller could return a string or dictionary to the web. So when you meet problem in development, you could disable the template by passing no arguments in expose funciton, such as “@expose()”. the web page will show the string or dict. This approach helps you debug the output of your controller method.

You could pass the json format (which looks like the pickle file) to get the complex output as well. pass “format=’json’” in expose funciton will return the result as json format.

@expose(format=’json’)

then you can ignore templating all together and make its getting set.

Form Handling

When using TurboGears, your controller methods get their arguments built from the various GET, POST, and URL mechanisms provided by CherryPy. Since the arguments are from GET/POST/URL, All the arguments will be strings.

For example:

/view?id=5&page=10
/view/5/10

are equivalent arguments for TurboGears method:

@expose()
def view(self, id, page):
    ....
    return dict()

Convert url strings to python types

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

from turbogears import controllers, expose
class Root(controllers.RootController):

#...
    # return the result of x+y
    @expose()
    def addnum(self, x, y)
        try:
           return str(int(x)+int(y))
        except:
           return 'value is not valid'

You’d like more arguments converted to their normal Python datatype: numbers to int, dates to datetime, etc. That sort of work fagged you out this approach is simple but far away from the clean code and DRY(don’t repeated yourself). That’s where validate comes into play.

Data validation

'@validate‘ decorator is inherited from the formencode module. It does both validation and conversion at the same time. It could help you ‘validate’ the string to see if the string could be converted to the specific Python datatype.

Validation necessarily happens with every conversion; For instance, you may want to convert string representation of dates to internal date objects; that conversion can fail if the string representation is malformed.

from turbogears import validators, expose, validate
....
@validate(validators=dict(id=validators.int(), page=validators.int()))
@expose()
def view(self, id, page):
        ....
        return dict()

or:

@validate(validators={
            id:validators.int(),
            page=validators.int()}
         )
@expose()
def view(self, id, page):
        ....
        return dict()

Form Validation

We can use ‘Schema’ to handle the complex form Validation

let’s take double password confirm for example:

class MySchema(validators.Schema):
    email = validators.Email(resolve_domain=True)
    pwd1 = validators.String(not_empty=True)
    pwd2 = validators.String(not_empty=True)
    chained_validators = [validators.FieldsMatch('pwd1', 'pwd2')]

@expose()
@validate(validators=MySchema())
def ...

You could define FancyValidator instead of buildin validators, raise custom exception by formencode.Invalid

Check the documentation of the validate decorator for details, and see also http://formencode.org/Validator.html