I recently got my simple widget example working (thanks Kevin!). I'll
share my simple example here and try to explain it.
Start with creating a form. (I did this in a seperate file since I
didn't want to clutter up controllers.py)
myForms.py:
createUserForm = widgets.TableForm(widgets=[
widgets.TextField("userId",
validator=validators.PlainText()),
# widgets.TextField("userId",
validator=validators.PlainText(not_empty=True)),
widgets.TextField("emailAddress",
validator=validators.Email()),
widgets.TextField("emailAddress"),
widgets.TextField("age", default=0,
validator=validators.Int())])
That is your widget table form which you'll use in controllers.py:
@turbogears.expose( html="my.templates.createUser")
def createUser( self):
return dict(message="", form=myForms.createUserForm)
By passing form=myForms.createUserForm you are making form accessible
to the kid template. Later in the kid timplate you can simply call
form.insert(...)
You'll probably want a way to save that data too. (I've made it a
seperate function for simplicity.
Note that I've set inputform=myForms.createUserForm, this tells TG that
I'm using that form to validate.
@turbogears.expose( html="my.templates.createUser",
inputform=myForms.createUserForm)
def createUserSave( self, userId='', emailAddress='', age='',
submit=''):
# Check for validation errors
if cherrypy.request.form_errors:
return dict(message="", form=myForms.createUserForm)
# The user doesn't exist. Create the user
hub.begin()
u=TG_User( userId=userId, emailAddress=emailAddress,
displayName=userId, password="passwd" )
g=TG_Group.byGroupId("admin")
u.addTG_Group(g)
hub.end()
raise cherrypy.HTTPRedirect(turbogears.url("/login"))
So now we just have to use this form in the kid template
createUser.kid
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://purl.org/kid/ns#"
py:extends="'master.kid'">
<head>
<meta content="text/html; charset=UTF-8"
http-equiv="content-type" py:replace="''"/>
<title>Create User</title>
</head>
<body>
<h2>Create Account</h2>
<p>${message}</p>
<div py:replace="form.insert(action='createUserSave')"/>
</body>
</html>
The magic line is <div
py:replace="form.insert(action='createUserSave')"/>.
This will pretty much work how you'd expect. If the age is not a valid
number, it will return you to the input form with the correct error
message. I hope I got this all correct and explained it in a way that
isn't too twisted.
Caveat Emptor:
I have found a bug
widgets.TextField("userId",
validator=validators.PlainText(not_empty=True))
causes an error. I'm not sure why inserting not_empty=True does this,
but the insert code for the widgets doesn't like it. I've also not been
able to get the validdators.Email() to work as a widget validator
either. :(
Anyway, that should do it.
I was thinking that it might be nice to generate a list of useful
widgets that should be created. I was thinking something like
changePasswordForm - old password, new password field 1, new password
checked against field 1
loginForm - username, password
creditCardForm - card number, expiration
Since these are common to many web applications.
A more advanced widget set my be a shopping cart...
Anyway, just a thought.
Lucas.-