Web Applications: Say Hello! cs 110 notes
Want to learn how to build a web
application? This article provides the "hello world" of web
programming. You'll learn how to use Python and Google's App Engine to
create a dynamic page that says "hello" to the user.
Dynamic Web PagesServers handle requests (events): the user entering a URL, clicking on a link, or submitting a form. The user's action causes a request to be sent to a server.
Some requests are
simple and the server just returns a static web page in HTML format.
Many requests, however, are for dynamic web pages such as that of a
news site or social network. For these pages, the server invokes controller code which processes the request.
The controller accesses information from a database, performs computations, and ultimately generates a new HTML page sent to a browser.
HTML Templates An HTML template is like a form letter in which the name and address can be automatically replaced so that the letter is sent out to
many people.
HTML templates consist of HTML code and template variables, which are the parts of the page that are replaced with "live" data such as a news item.
In
this lesson, we'll be using Google's App Engine and controller code
written in the Python language. The HTML templates we'll use define
anything within double-curly-brackets as a template variable, e.g.,
<html> <body> Dear {{recipient}}, <p>You are a nice man</p> </body> </html>
HTML Forms For
command-line programs written in Python, we use the 'input' and
'raw-input' functions to get input data from the user. With web
applications, our user interface is HTML and we get input from the user
with an HTML component called a form. <form action="/say_hello" method="get"> first:<input type="text" name="first"><br/> last:<input type="text" name="last"><br/> <input type="submit" value="Say Hello"> </form>
If this HTML were rendered in a browser, you'd see:
The
form consists of a set of input components. In the example, there are
two text components, one named 'first', the other named 'last', and a
submit button.
Web applications are based on the client-server
model. The web page runs on the client (the browser). When the user
clicks on a submit button, a request is made to the server using the
data defined within the form.
Let's pretend our example came from the server http://sample.com,
and say the user entered 'Joe' and 'Smith' in the text boxes and then
clicked 'Say Hello'. Then the following URL would be invoked:
http://sample.com/say_hello?first=Joe&last=Smith
Here 'say_hello' is the action defined in the form, and first and last are the names of the text boxes within the form.
The URL is something like a function call in Python, where the function is say_hello, the formal parameters are first and last, and the
actual parameters are 'Joe' and 'Smith'.
Here, the browser
sends a request to the server, sample.com. The server processes the
request and sends back a new page, with result information, to the
browser.
Responding to Forms: The Controller We call the web server code that handles requests the controller. We'll be working with controllers written in the Python language. With
a Google App Engine server, your controller code maps a request action to a controller
class method. The mapping table is defined near the bottom of the controller file:
application = webapp.WSGIApplication(
[ ('/', MainPage),
('/say_hello', SayHelloHandler) # map request to a class
],
debug=True)
For this example, the /say_hello action is
mapped to the class SayHelloHandler. Most server code will define a
number of actions that it can "handle". For instance, the sample above
also maps the main page of the site, denoted with '/' to a class called
MainPage.
The definitions for each handler class are found
elsewhere in the controller file. For example, the sayHelloHandler
would look something like the following:
class SayHelloHandler(webapp.RequestHandler): def get(self): first=self.request.get('first') last=self.request.get('last') # do some computations, access database # set up template values # render a page for the browser
In this incomplete handler, the parameters 'first' and 'last' of the request are accessed through the self.request.get method. Note also that the handler code is in a get function to match the 'method=get' specified in the HTML form.
Generally,
the server code will use the input parameters to access/modify a
database, perform some computations, and ultimately render a new web
page containing the results of the computations. For instance, the
server code might access the personal profile matching the first and last name
given in the parameters, then send this profile information as part of
the rendered page.
For our example, we'll just build a string which says hello to the user:
class SayHelloHandler(webapp.RequestHandler): def get(self): first=self.request.get('first') last=self.request.get('last') # set up template value messageString = 'hello ' + first template_values={'message': messageString} path = os.path.join(os.path.dirname(__file__),'response.html') self.response.out.write(template.render(path,template_values))
This
code creates a variable messageString that concatenates 'hello' with
the first name, e.g., 'hello Joe'. To get this string back to the
client, we stick it into a variable called 'template_values'.
template_values is a hash array that holds a list of key-value pairs.
In this case there is one key, 'message' which is mapped to the value
of the variable 'messageString'.
The second to last line in the controller code specifies that the file
response.html should be rendered. response.html is called an 'HTML
template', which is something like a form letter where the name and
address can be automatically replaced so that the letter is sent out to
many people. In this case, the replaceable part of response.html is the
message, and it is specified with a template variable defined within
double-curly brackets:
<html> <body> <p> {{ message }} </p> </body> </html>
When the template is rendered, the {{message}} is replaced with the value that the controller defined in template_values, e.g., 'hello Joe'.
Other input typesThe
above example is for text input, but HTML provides a number of other
input widgets including radio buttons, checkboxes, and drop down
listboxes. Check out this tutorial from http://www.w3schools.com/html/html_forms.asp for details.
Your Turn
Part I: Implement the say_hello web application described in this page.
1. Save the attachments
at the bottom of this page (https://sites.google.com/site/usfcomputerscience/html-forms) into a folder 'say_hello'. First create a sub-folder in your home directory named 'say_hello'. Then right-click on each attached file and choose 'Save Link As'. Be sure and
name them exactly as they are named in the attachment, and save them in your 'say_hello' subfolder.
2. Start Google's App Engine Launcher. Open a command-line terminal and enter "appengine_launcher". This program allows you to test and deploy web apps on Google's servers.
3. Open the project you just downloaded. In the Launcher window, choose File | Add Existing Application. Then browse to your 'say_hello' folder and choose it.
4.
Run the app on the (local) test server. Choose your app on the list that appears in the launcher and click the green "Run' button. This starts a test web server on your machine. You can access your app by typing the following in a browers:
http://localhost:8080
When the page loads you'll see a form requesting your first an last name. Enter them and click "Submit". The program should respond by saying hello.
5. Deploy to the web. If you've
made it this far, your web app works, but its really not on the web
yet-- your browser is just accessing a 'test' server on your local
machine. Now we'll upload your application to the web, and specifically
Google's App Engine servers:
- The first step is to register or sign-in with Google's App Engine service. Go to http://appengine.google.com/start If you are registering, you'll have to step through the registration process, including giving Google your cell phone #.
- Once
you
are signed in, click 'Create Application' and set the application
identifier to something like 'DavesSayHello', but with your name
instead of 'Dave'. The name can be anything, but it has to be unique in
the Google system.
- You
need to put the name of your application, which you just set at Google,
into the configuration file of your application, app.yaml (the one you
downloaded from the attachments on this page). So open a text editor,
then go to your 'say_hello' folder and open the file 'app.yaml'. The first line of text in that file is the
application name, and says 'application: yourappname'. Change
'yourappname' to the application identifier you just registered and
save the file.
- You're now ready to upload your program to Google. In the App Engine Launcher, click "Deploy".
6.
To run your application, go to a browser and enter the name of your
application, followed by 'appspot.com'. For instance, if your
application identifier was 'DavesSayHello', then enter
'DavesSayHello.appspot.com' in your browser.
If
all is well, you should see a web page that looks the same as when you
ran your program with the development server. Only this time, your
application is really running on the web!
PART II. Modifying the code.1. First, let's make it so that the hello message appears directly on the home page (index.html) instead of in a separate file.
- Open index.html in a text editor and add the text: {{message}} below the form (but above the \body tag)
- Open the say_hello_controller.py file and find where it refers to 'response.html'. Change 'response.html' to 'index.html'. This will cause the message to appear directly on the home page.
- Test the app on the local server by entering "localhost:8080" in the browser, entering a name, then clicking "Submit".
2. Modify the app so that the hello message refers to the full name (first and last) and also reports the length of the person's first name, e.g.,
Hello Jimmer Fredette, your first name has 6 letters in it
- In say_hello_controller.py, build the variable 'messageString' so it has all the information you need.
- You'll need to use string concatenation (+) and the str function.
3. Its better to put static information in the HTML file and only dynamic data in the controller. Modify the controller so that, in the template values, it sends back the name and lengthe of the first name as two separate template values (name and nameLength). You can put more than one thing in the template_values by separating with commas, e.g.,
template_values = {'name':name, 'nameLength':nameLength}
You'll also need to modify index.html so that it has the "Hello" and the "your first name has" and the "letters in it" directly, and so that it has two template valus:
{{name}} and {{nameLength}}.
4. Create a new folder named 'diceGame' and copy all of the files from 'say_hello' into it. Then modify the files to create an app that lets the user click on a button to roll a dice. The app should report the roll, and each time the button is clicked a random number between 1 and 6 should appear.
|
ď David Wolber, Sep 16, 2009 11:56 AM
ď David Wolber, Sep 16, 2009 11:56 AM
ď David Wolber, Sep 16, 2009 11:56 AM
ď say_hello_controller.py (1k) David Wolber, Sep 16, 2009 11:56 AM
|