Wednesday, October 5, 2011

LPTHW - Exercise 51

In this exercise, we learn how to deal with form input and a bit about testing web apps.

The first thing I did was to change app.py and refactor it to handle web input. We will handle simple input as GET input parameters to start with.

Here is the new app.py file:

import web
urls = (
'/hello', 'Index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class Index(object):
def GET(self):
form = web.input(name="Nobody")
greeting = "Hello, %s" % form.name
return render.index(greeting = greeting)
if __name__ == "__main__":
app.run()
view raw app.py hosted with ❤ by GitHub


Now if you notice, in this file we use the line

form = web.input(name="Nobody")

to handle the input. If the input contains a 'name' parameter, then we will use it, else it will default to "Nobody", since we have given a default value as an argument to the function call.

Getting the values as url parameters is not a good idea:

This is a good beginning, but we should really be getting the values in a form and not as command line parameters. For this we will need to add some HTML and a method in the Index class to handle POST data (since this is the default method for sending form data).

I made a few changes to app.py, index.html, and added a new file hello_form.html All the code is embedded below:

#This app.py handles POST data from the hello_form
import web
urls = (
'/hello', 'Index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class Index:
def GET(self):
return render.hello_form()
def POST(self):
form = web.input(name="Nobody", greet="Hello")
greeting = "%s, %s" % (form.greet, form.name)
return render.index(greeting = greeting)
if __name__ == "__main__":
app.run()
view raw app.py hosted with ❤ by GitHub
<!-- This template works with the modifications to handle POST data -->
<html>
<head>
<title>Sample Web Form</title>
</head>
<body>
<h1>Fill Out This Form</h1>
<form action="/hello" method="POST">
<p>
A Greeting: <input type="text" name="greet" />
</p>
<p>
Your Name: <input type="text" name="name" />
</p>
<p>
<input type="submit" />
</p>
</form>
</body>
</html>
view raw hello_form.html hosted with ❤ by GitHub
<!-- This template works with the modifications to handle POST data -->
<html>
<head>
<title>Gothons Of Planet Percal #25</title>
</head>
<body>
<p>
<a href="/hello">Home</a>
</p>
$if greeting:
I just wanted to say <em style="color: green; font-size: 2em;">$greeting</em>.
$else:
<em>Hello</em>, world!
</body>
</html>
view raw index.html hosted with ❤ by GitHub


Don't repeat boilerplate code:

It's very good that we can now handle form data. However, the observant programmer must have noticed that both index.html, and hello_form.html have common boilerplate code. It would be good if we can remove the repetition. Well, we can, if we use templates.


All the code which uses templates is embedded below:

import web
urls = (
'/hello', 'Index'
)
app = web.application(urls, globals())
render = web.template.render('templates/', base="layout")
class Index:
def GET(self):
return render.hello_form()
def POST(self):
form = web.input(name="Nobody", greet="Hello")
greeting = "%s, %s" % (form.greet, form.name)
return render.index(greeting = greeting)
if __name__ == "__main__":
app.run()
view raw app.py hosted with ❤ by GitHub
<h1>Fill Out This Form</h1>
<form action="/hello" method="POST">
<p>
A Greeting: <input type="text" name="greet" />
</p>
<p>
Your Name: <input type="text" name="name" />
</p>
<p>
<input type="submit" />
</p>
</form>
view raw hello_form.html hosted with ❤ by GitHub
$def with (greeting)
<p>
<a href="/hello">Home</a>
</p>
$if greeting:
I just wanted to say <em style="color: green; font-size: 2em;">$greeting</em>.
$else:
<em>Hello</em>, world!
view raw index.html hosted with ❤ by GitHub
$def with (content)
<html>
<head>
<title>Gothons From Planet Percal #25</title>
</head>
<body>
$:content
</body>
</html>
view raw layout.html hosted with ❤ by GitHub

No comments:

Post a Comment