4.3. A Simple Form to Add Bookmark
TurboGears has lots of tools to help you build, validate, and process form data. There's a web-based data editing tool in the TurboGears toolbox, and even an experimental FastData class to automate form creation for your model classes.
We cover each of these tools, but for now let's create a new method to our controller to add new bookmarks and feed data to it from a simple web form. Rather than do this all in one big step, let's start by creating a save_bookmark method in our controller that adds a predefined bookmark to the database. We set up some variables, and then create a new Bookmark object with the exact same syntax we used earlier in the chapter when we created our first bookmark through tg-admin shell.
By now, the code to do this should look familiar to you:
@expose() def save_bookmark(self): name="Blue Sky on Mars" link="http://blueskyonmars.com" description="Another not so random link." Bookmark(name=name, link=link, description=description) raise redirect("/list")
This method sets up a few variables, and then creates a new Bookmark object using the exact same syntax we used earlier in the chapter when we created our first bookmark through tg-admin shell. When our new record is added to the database, the user will be sent the results of the /list page.
After you add this method, you can check to see that this works by browsing to http://localhost:8080/save_bookmark, and you should see the new bookmark in the list.
Of course, we don't really want to hard-code bookmarks to be added, so we can adjust the code to do something like this:
@expose(template="bookmarker.templates.add") def save_bookmark(self, name, link, description): b=Bookmark(name=name, link=link, description=description) raise redirect("/list")
This saves a new bookmark into the database, and then redirects the user to the standard list view. But now we need to get the name, link, and description variables from somewhere. Remember from Chapter 3 that CherryPy turns HTTP Post names and values directly into named parameters that will be passed into your exposed object? So, all you need to do is create a form that submits a name, link, and description to the /save_bookmark URL and everything will work.
You can copy list.kid to form.kid and edit the body to add a form. Here's the basic HTML you need in the body of form.kid:
<body> <form NAME="Add Bookmark" METHOD="post"ACTION="/save_bookmark"> <p>Name: <input name="name"></input></p> <p>Link: <input name="link"></input></p> <p>Description:<textarea name="description" rows="4" cols="30"></textarea></p> <p><input type="submit" value="submit"></input></p> </form> </body>
This form submits its contents to the server, and CherryPy calls save_bookmark with the form inputs as named parameters, and save_bookmark adds the bookmark to the database and then redirects the user to /list.
To publish form.kid, we need one final step. We add a new method to our controller that looks like this:
@expose(template="bookmarker.templates.form") def bookmark(self): return dict()
Now, if you browse to http://localhost:8080/bookmark, you'll get a form, and when you fill out that form, a new bookmark will be added to the database.
That's about all it takes to build a basic user input mechanism with TurboGears. Of course, there's a lot more that could be done. Our form and list pages aren't attractive, so some HTML/CSS magic would help a lot. But more important, there's no code to edit existing forms, delete unwanted bookmarks, or handle data validation. We cover all of that in the next chapter.