Using in a TurboGears Form

The goal of this tutorial is to get a tw.forms form to go through two layers of validation before passing:

  1. Use the validation packages provided by tw.forms and formencode
  2. If the first layer of validation passes, try to run the charge using the authorize package. If this returns a response code of 1 (approved) then all validation has passed. Otherwise, invalidate the form and flash the error.

The Authorize Package

The authorize package handles requests, and can be found here or by typing: easy_install authorize

Defining The Validator

First we will need to define our ProcessCard() class which will be the chained FancyValidator for processing the card:

import tw.forms as twf
from authorize import aim as aim_api

# FancyValidator to process the Credit Card using the authorize package
class ProcessCard(twf.validators.FancyValidator):
    def _to_python(self, value, state):
        # Setup the aim Api object.
        aim = aim_api.Api(AUTHNET_LOGIN, AUTHNET_KEY, is_test=False)

        # Create a transaction against a credit card
        result_dict = aim.transaction(
            # ...and others...

        if result_dict['code'] == '1':
            # success
            return value
            # failure
            raise twf.validators.Invalid(result_dict['reason_text'], value, state)

Defining The Form

Next we’ll define our form class that will end up being passed to the view:

from tw.api import WidgetsList

class AuthnetForm(twf.TableForm):
    submit_text='Process Card'

    # specify chained validators
    validator = twf.validators.Schema(
        chained_validators = [
            # you could also add an expiry validator, but authnet will handle this for you

    # specify form fields
    class fields(WidgetsList):
        name = twf.TextField(validator=twf.validators.String(not_empty=True))
        # ...and others like address, city, state, zip...
        spacer = twf.Spacer(suppress_label=True)
        card_type = twf.SingleSelectField(options=[('visa', 'Visa'),
                                                   ('mastercard', 'Master Card'),
                                                   ('discover', 'Discover'),
                                                   ('amex', 'American Express')], validator=twf.validators.NotEmpty)
        card_expiry = twf.CalendarDatePicker(date_format="%m/%Y", validator=twf.validators.NotEmpty)
        card_number = twf.TextField(label_text='Card #', validator=twf.validators.NotEmpty)
        card_cvv = twf.TextField(label_text='CVV Code', validator=twf.validators.NotEmpty)

Using It In A Controller

Now all you have to do is set up your controller class methods to use the form:

# Assign a name to the form
authnet_form = AuthnetForm('authnet_form', action='/authnet/process/')

class AuthnetController(BaseController):
    def index(self, **kw):
        if '_the_form' in tmpl_context.form_errors:
            # if we have top-level form errors, use flash() to display them
            flash(tmpl_context.form_errors['_the_form'], 'error')
        # Use ${form()} to print the form in your template
        return dict(form=authnet_form)

    @validate(authnet_form, error_handler=index)
    def process(self, **kw):
        # if validation passes, this method will run (specified by form action)
        return 'Card was successfully charged!'