#---- 8< ----- myproj/myproj/forms/base.py -----"""Base classes for forms"""from formencode.schema import Schemaclass FilteringSchema(Schema): """ Schema that gets around the of toscawidgets in tg1 having self passed as a field. """ # TODO: Get rid of this when we upgrade to tg2 filter_extra_fields = True allow_extra_fields = True#----- 8< ------- myproj/myproj/forms/site.py"""Tosca widgets form for a CMS Site"""from toscawidgets.api import WidgetsList, CSSSource, JSSourcefrom toscawidgets.widgets.forms import TableForm, TextField, HiddenFieldfrom toscawidgets.widgets.forms.validators import UnicodeString, Intfrom toscawidgets.js import js_functionfrom cms.forms.base import FilteringSchema# Lil' chunk o' CSS for tasty eye-candy ;)# External css files can be wrapped with CSSLinkcss = CSSSource("""label.required, .fielderror { font-weight: bold; color: red;};""")# We define the source for some JS functions we're going to interface# External js files can be wrapped with JSLinkfunctions = JSSource("""var focus_element = function (elem) { var elem = document.getElementById(elem); elem.focus(); elem.select(); }; """, )alert = js_function('alert')focus_element = js_function('focus_element')class SiteForm(TableForm): class fields(WidgetsList): clientId = HiddenField(validator=Int()) siteId = HiddenField(validator=Int()) newSite = HiddenField() url = TextField(validator=UnicodeString(not_empty=True)) title = TextField(validator=UnicodeString(not_empty=True)) notes = TextField(validator=UnicodeString()) validator = FilteringSchema() # allow adding js calls dynamically for a request include_dynamic_js_calls = True css = [css] javascript = [functions] def update_params(self, d): super(SiteForm, self).update_params(d) # Focus and select the 'title' field on the form # The adapter we just wrote lets us pass formfields as parameters and # the right thing will be done. if not d.error: self.add_call(focus_element(d.c.title)) else: self.add_call( alert('The form contains invalid data\n%s'% unicode(d.error)))#--------- 8< -------- Somewhere in your controllersfrom cms.forms.site import SiteFormclass SuperController(controllers.Controller): siteForm = SiteForm(); @expose(template="cms.templates.editSite") @require(in_group("manager")) def editSite(self, clientId=None, siteId=None, url=None, title=None, notes=None, newSite=None, tg_errors=None, tg_exceptions=None, tg_source=None): """ Shows a form for editing the info of a site """ # We are just showing the edit form if not siteId: return { 'newSite': True, 'client': Client.query.get(clientId), 'form': self.siteForm, } else: return { 'newSite': False, 'site': Site.query.get_by(id=siteId), 'form': self.siteForm, } @error_handler(editSite) @validate(siteForm) @expose() def saveSite(self, siteId=None, url=None, title=None, notes=None, newSite=None, clientId=None): """ Where the site form posts to """ if newSite: # Make a new site client = Client.query.get(clientId) site = Site(client=client, url=url, title=title, notes=notes) else: # Editing an existing site site = Site.query.get(siteId) if clientId != site.client.id: site.client = Client.query.get(clientId) site.url = url site.title = title site.notes = notes site.save() session.commit() return self.showSite(site=site)---------8< ------- in the template (I'm using genshi) <div id="editSite" py:if="not newSite"> ${form.display( action="saveSite", value=dict( newSite=newSite, siteId=site.id, siteTitle=site.title, siteURL=site.url, siteNotes=site.notes, ), )} </div> <div id="newSite" py:if="newSite"> ${form.display( action="saveSite", value=dict( newSite=newSite, clientId=client.id, ), )} </div>