Make Donations

Recent site activity

Tutorials‎ > ‎

Create a Todo-List Application



In this application, you see how to use GAEO to build a Todo-List application. The application will show you the user authentication flows and process data of different users. Let's start by designing the mockup of this application.

Design Phase

--

The Mockups

--

Design The Models

--

Implementation Phase

--

Create The Project

To start creating the project, you have to be sure that you've installed the Google App Engine SDK and (the current) GAEO packages. After preparing the necessary packages, you can create a project as the following command (use this command in your console):

Command 1. Create The utodo Project.

~/$ gaeo utodo


The gaeo script will create a utodo directory that includes the basic project files. The application's identifier is also utodo. Note that if you installed GAEO by unzipping the released package, maybe your script name is gaeo.py instead of gaeo.

Define The Models

Let's begin to design the models in this application. There are three models are necessary -- User, Todo, and Counter. The User model stores the user information; the Todo model stores all todo items; the Counter model is used to count the entries since the Bigtable isn't good at counting.

Command 2 shows how to use gaeogen script to generate the model templates.

Command 2. Use gaeogen To Generate Models

~/utodo$ gaeogen model User
Creating Model user ...
...
~/utodo$ gaeogen model Todo
Creating Model todo ...
...
~/utodo$ gaeogen model Counter
Creating Model counter ...
...

Now you have user.py, todo.py and counter.py files in the ~/utodo/application/model directory. The Code 1 is the inplementation of these models.

Code 1. Design The Models (user.py, todo.py, and counter.py)

# application/model/user.py
from google.appengine.ext import db
from gaeo.model import BaseModel

class User(BaseModel):
    name = db.StringProperty(required=True)
    profile = db.StringProperty(multiline=True)
    created = db.DateTimeProperty(auto_now_add=True)

# application/model/todo.py
from google.appengine.ext import db
from gaeo.model import BaseModel
from model.user import User

class Todo(BaseModel):
    title = db.StringProperty(required=True)
    desc = db.TextProperty(required=True)
    status = db.IntegerProperty(required=True, default=0)
    created = db.DateTimeProperty(auto_now_add=True)
    updated = db.DateTimeProperty(auto_now=True)

Todo.belongs_to(User)


# application/model/counter.py
from google.appengine.ext import db
from gaeo.model import BaseModel

class Counter(BaseModel):
    name = db.StringProperty(required=True)
    count = db.IntegerProperty(required=True, default=0)

Since the todo item belongs to one user, we use the belongs_to method to construct the relationship between User/Todo model. In the remaining section, you will see how we specify a todo item to an user.

The Welcome Page and User Sign-up

In the / page (Welcome controller and index action), we put a sign-in url for user login. The Google App Engine provides a Google account sign in/out api so that the user can login a Google App Engien application by using her Google (or Google Apps) account. In the utodo application, we connect the user model to a logined Google account. Now lets add the signin link in the welcome page. Code 2 shows the html:

Code 2. Put Sign-in Link on the Welcome Page. (application/templates/welcome/index.html)

<h1>utodo application</h1>
<a href="{{signin_url}}">Sign in</a> to manage your Todo list.

In this HTML file, we insert a link and the link is stored as template variable -- signin_url. We have assign value to this variable in the controller. Code 3  shows the assignment in the action.


Code 3. Assign signin_url Value in Controller (application/controller/welcome.py)

class WelcomeController(BaseController):
    def index(self):
        from google.appengine.api import users
        self.signin_url = users.create_login_url('/user/home')

We create a Google account signin URL by using the App Engine's Users Service and specify a redirection to /user/home. That means if user successfully sign in with her Google account, the authentication page will redirect her to the http://yourhost.com/user/home. The /user/home URL stands for the GAEO router will dispatch the request to the home action in User controller. We can also create the User controller with the following command:

Command 2. Create the User Controller.

~/utodo$ gaeogen controller User signup home
Creating ....

With Command 2, we created an User controller and two actions (w/ template files). Since the signed users reach the /user/home, we have to check if the user first time login utodo. If she is a new comer, it's necessary to take her to the /user/signup to create a new utodo account (yes, connect her Google account to the utodo account). Code 5 shows how to check it.

Code 5. Check If The User Is A New Comer. (application/controller/user.py)

...
    def home(self):
        from google.appengine.api import users
        from model.user import User
        # retrieve the logined Google account information
        google_acct = users.get_currnet_user()
        # TODO: if google_acct is None, take to the login page
        # get an user entity with the email address
        utodo_user = User.get_by_key_name(google_acct.email())
        if utodo_user is None:
            self.redirect('/user/signup')

As you can see, we will use the Google account's email address to be the key_name of an utodo user entity (will be mentioned later). If the user hadn't signed up an utodo account, the utodo_user will be None and we take her to the /user/signup page.

Now, put a sign-up form in the /user/signup page.

Code 6. Add a Sign-up Form. (application/templates/user/signup.html)

<form method="post" action="/user/create">
    <fieldset>
        <legend>Sign Up An Utodo Account</legend>
        <p>
            <label>Name:</label><br>
            <input type="text" name="user[name]" id="user_name">
        </p>
        <p>
            <label>Profile:</label><br>
            <textarea name="user[profile]" id="user_profile" rows="3" cols="40"></textarea>
        </p>
        <p>
            <input type="submit" value="Sign Up">
        </p>
    </fieldset>
</form>

The form data will be sent to the /user/create to create an utodo account. So we add the create action in the User controller as Code 7.

Code 7. The /user/create Action (application/controller/user.py)

....
    def create(self):
        from google.appengine.api import users
        from model.user import User
        from model.counter import Counter
        # retrieve the form data
        data = self.params['user']
        google_acct = users.get_current_user()

       
        # create a user entity and set the key_name to the
        # Google account's email address.
        u = User(key_name=google_acct.email(),
       
         name=data['name'],
                 profile=data['profile'])
        u.put()

        # add user counter
        c = Counter.get_by_key_name('user')
        if c is None:
            c = Counter(key_name='user', name='user')
        c.count += 1
        c.put()
        # redirect to /user/home
        self.redirect('/user/home')

In the create action, we create an utodo user according to the data sent from sign-up form. Since we specify the form field names as an user array, we can retrieve the array through self.params and it returns an array, too. After creating the user entity, it takes user to /user/home page.

In current step, we leave /user/home blank first. Let's process Todo items now.

Create and List Todo Items

--

Edit and Delete the Todo Items

--


Enhancement Phase

--