Make Donations

Recent site activity

Tutorials‎ > ‎

Create a Simple Guestbook Application


Create project

As the previous section mentioned, let's use gaeo.py to create a gbook application.

# gaeo gbook

Message Form

First, we create a form for the visitor to leave messages. The root page (url '/') is default dispatched to the welcome controller and index action. That means if you want to do anything on the root page, you need to add codes in the welcome controller.

The welcome controller is a WelcomeController class, which locates in the application/controller/welcome.py [1]. Now, the content of welcome.py should be like this:

from gaeo.controller import BaseController

class WelcomeController(BaseController):
    def index(self):
        pass

There's a WelcomeController class with a index method. Yeah, the index method stands for the handler of index action. Now, just leave it blank (i.e. one line code -- pass) at this time.

Since the URL '/' is dispatched to welcome controller and index action, the default output is the application/templates/welcome/index.html template. Let's add a form in this file with the following content:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>GAEO Book</title>
    </head>
    <body>
      <form method="post" action="/speak">
        <fieldset>
            <legend>Leave a message</legend>
            <p>
                <label>Name:</label><br>
                <input type="text" name="username" size="20">
            </p>
            <p>
                <label>Message:</label><br>
                <textarea name="message" rows="5" cols="40"></textarea>
            </p>
            <p>
                <input type="submit" value="Post">
            </p>
        </fieldset>
      </form>
    </body>
</html>

Thus, we create a web form with 2 fields, one is used to fill the visitor's name and the other is her message. While the visitor pushes the Post button, the form sends a HTTP Post request to the URL '/speak'. Now, we have to handle this request.

Add routing rules

Although GAEO has default URL routing rules (for example, '/' is dispatched to {'controller': 'welcome', 'action': 'index'}), there's no default rule for URL '/speak'. It's easy to add a custom rule in your application. Open the main.py file and find the initRoutes method:

def initRoutes():
    r = router.Router()

    #TODO: add routes here

    r.connect('/:controller/:action/:id')

The above code is generated by the gaeo.py script. We may add the rule of URL '/speak' here as the following

def initRoutes():
    r = router.Router()
    r.connect('/speak', controller='welcome', action='speak')
    r.connect('/:controller/:action/:id')

After adding the line of code, the URL '/speak', now, will be dispatched to welcome controller and speak action. So, we have to add a speak method in the WelcomeController class for handling the '/speak' requests.

Store the data

Before we implementing the speak method, let's specify the data model first. In your application's directory root (e.g., /home/ericsk/Demos/gbook), use gaeogen.py script to generate a data model class with this command:

gaeogen model Message

The first argument is the type of generation and the second is the name of data model. The above command generates a Message class in the application/models/message.py file. It should be

from google.appengine.ext import db
from gaeo.model import BaseModel

class Message(BaseModel):
    pass

Besides generating the model, we have to define which data we want to store in this model. So we add some codes like this:

from google.appengine.ext import db
from gaeo.model import BaseModel

class Message(BaseModel):
    username = db.StringProperty(required=True)
    content = db.TextProperty(required=True)
    post_at = db.DateTimeProperty(auto_now_add=True)

We stores 3 fields in this mode:
  • username stores the visitor's name.
  • content stores the visitor's message.
  • post_at stores the time that the message is left.
These codes use the Datastore API to define the data field's type. If you want to know what the types mean or how many types you could use, please visit the App Engine's documentation page.

Process and store the data

Let's get back the speak action. Since we add a custom rule that makes URL '/speak' be dispatched to {'controller':'welcome', 'action':'speak'}, we have to add a speak method in the WelcomeController:

# application/controllers/welcome.py
from gaeo.controller import BaseController

# import the model class
from model.message import Message

class WelcomeController(BaseController):
    def index(self):
        pass
        
    def speak(self):
        try:
            # create a model instance and fill the data from request parameters
            msg = Message(
                    username=self.params['username'],
                    content=self.params['message']
                    )
            # store the data
            msg.put()
            # redirect to URL '/'
            self.redirect('/')
        except Exception, ex:
            # show the exception message
            self.render(text='Exception: %s' % ex)

It's simple to store a data in the App Engine's bigtable -- create a model instance and invoke put method to store it. The requested data (from the message form) are stored in the self.params object (it's a dict) and the key is mapped to the form field's name property. While we complete storing the data, we redirect the request to the URL '/'.

If there's an error occurred, the except block will show the exception message to the brower through self.render method.

Check the storage

Before we presenting the messages, we should check if the data are correctly stored in the bigtable. You can visit http://localhost:8080/_ah/admin/datastore to check the storage (on your machine). In the Entity Kind: field, type Message to see all the stored Message data.

If you are using the Launcher, you can visit this page via the SDK Console tab.

Present the stored messages

If the messages are correctly stored, we can show them on the page in a readable format. If we want to show the message in the root page, we have to fetch the data in the index action:

# application/controllers/welcome.py
...

def index(self):
    # fetch all the messages
    self.msgs = Message.all()
    # sort them with the descending order of post_at
    self.msgs.order('-post_at')
    self.msgs.fetch(50)

...

We added an instance variable in the controller and this variable will be sent to the template for rendering. Now, open the index's template to show the messages.

<!-- application/templates/welcome/index.html -->
...
...
<div id="messages">
  {% if msgs %}
  <ul>
    {% for msg in msgs %}
    <li>
      <h3>{{ msg.username }}:</h3>
      <p>{{ msg.content }}</p>
      <hr>
      <p style="text-align:right;"><small>At {{ msg.post_at|date }}</small></p>
    </li>
    {% endfor %}
  </ul>
  {% else %}
  <h1>There's no messages.</h1>
  {% endif %}
</div>
...
...

Finally, we have a simple guestbook application, now.