Version 0.6
Copyright © 2008 - 2009 Lars Vogel
17.08.2009
| Revision History | ||
|---|---|---|
| Revision 0.1 | 21.12.2008 | Lars Vogel |
| Created based on the introduction tutorial from Google | ||
| Revision 0.2 | 26.12.2008 | Lars Vogel |
| Changed from the Google tutorial to simple todo list. Added email notification. | ||
| Revision 0.3 | 27.12.2008 | Lars Vogel |
| Display table only if there are todos. Formated the created / updated date. Created anchor for the hyperlinks | ||
| Revision 0.4 | 07.01.2009 | Lars Vogel |
| Introduced Eclipse of Python development | ||
| Revision 0.4.1 | 08.04.2009 | Lars Vogel |
| Changed "only Python is supported" | ||
| Revision 0.5 | 17.06.2009 | Lars Vogel |
| Add link to Python with Eclipse article | ||
| Revision 0.6 | 17.08.2009 | Lars Vogel |
| Removed Pydev Eclipse plugin installation with reference to the Python article | ||
Google App Engine - Python
This article describes the creation of a web application with Python on the Google App Engine.
The example created in this article will be a simple Todo list. The usage of the email API will get demonstrated. Also conditions in the Django web template and formating of dates will get demonstrated.
The article demonstrates optionally the usage of Eclipse for developing, running and debugging the Google App Engine application.
Table of Contents
Google offers with the Google App Engine(GAE) a cloud computing infrastructure for creating and running web application on the Google infrastructure.
The GAE is a platform to create web applications. Google does currently support Python, Java and several languages based on Java as a programming language for the Google App Engine. This article will focus on the development with Python but no previous knowledge of Python is required. See the resource part of a link to an introduction to the Google Apps Engine Development with Java.
Cloud computing allows that system resources can be dynamically allocated to the application on demand. Currently the price model for the Google App Engine is not defined but Google offers a free starting offer for the GAE.
Currently a user can create a maximum of 10 application on the Google App Engine.
Download and install Phython 2.5.2. This is the version that runs on the Google App Engine and should therefore be used. http://www.python.org/download/releases/2.5.2/
Download the Python version of the Google App Engine from Download Site for the GAE . The main page for the GAE is http://code.google.com/intl/en/appengine/
On the main page you need to created an account if you have not yet done so.
In this part of the tutorial we will develop a small Todo list. This list will allow you to store todos, send out email reminders to yourself and delete todos. You can also store an URL and a description to each todo.

The source of this example is stored in project "de.vogella.gae.python.todo" and can be browsed on www.vogella.de source code
Create a new directory "googleappengine01", e.g. c:\temp\googleappengine01. All the following files must be created within this directory.
Create the following configuration file for your application. It define the application name, the runtime and defines the handler script which should get invoked for a specific URL.
application: googleappengine01 version: 1 runtime: python api_version: 1 handlers: - url: /css static_dir: css - url: /images static_dir: images - url: /.* script: todo.py
The script defines that all URL request will be handled by the script "todo.py". It also defines two static directories in which static content is stored which can also be served. Without this definition the Google app engine would not deliver this content to the webbrowser.
Python allows to define several classes in one source file. We are going to create the following classes:
TodoModel: Defines the data model for your application.
MainPage: Serves as the main entry point, user validation is checked here
New: This class will create the new Todo in the database
Done: Marks the todo as complete and deletes it from the database
Email: Sends the selected todo to yourself via email as a reminder
Create the file "todo.py" with the following content. Study the source code; I tried to document it well in the hope that it is self-explaining.
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from google.appengine.api import mail
# Todo defines the data model for the Todos
# as it extends db.model the content of the class will automatically stored
class TodoModel(db.Model):
author = db.UserProperty(required=True)
shortDescription = db.StringProperty(required=True)
longDescription = db.StringProperty(multiline=True)
url = db.StringProperty()
created = db.DateTimeProperty(auto_now_add=True)
updated = db.DateTimeProperty(auto_now=True)
dueDate = db.StringProperty(required=True)
finished = db.BooleanProperty()
# The main page where the user can login and logout
# MainPage is a subclass of webapp.RequestHandler and overwrites the get method
class MainPage(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
if user:
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
# GQL is similar to SQL
todos = TodoModel.gql("WHERE author = :author and finished=false",
author=users.get_current_user())
values = {
'todos': todos,
'numbertodos' : todos.count(),
'user': user,
'url': url,
'url_linktext': url_linktext,
}
self.response.out.write(template.render('index.html', values))
# This class creates a new Todo item
class New(webapp.RequestHandler):
def post(self):
user = users.get_current_user()
if user:
testurl = self.request.get('url')
if not testurl.startswith("http://") and testurl:
testurl = "http://"+ testurl
todo = TodoModel(
author = users.get_current_user(),
shortDescription = self.request.get('shortDescription'),
longDescription = self.request.get('longDescription'),
dueDate = self.request.get('dueDate'),
url = testurl,
finished = False)
todo.put();
self.redirect('/')
# This class deletes the selected Todo
class Done(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if user:
raw_id = self.request.get('id')
id = int(raw_id)
todo = TodoModel.get_by_id(id)
todo.delete()
self.redirect('/')
#This class emails the task to yourself
class Email(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if user:
raw_id = self.request.get('id')
id = int(raw_id)
todo = TodoModel.get_by_id(id)
message = mail.EmailMessage(sender=user.email(),
subject=todo.shortDescription)
message.to = user.email()
message.body = todo.longDescription
message.send()
self.redirect('/')
# Register the URL with the responsible classes
application = webapp.WSGIApplication(
[('/', MainPage),
('/new', New),
('/done', Done),
('/email', Email)],
debug=True)
# Register the wsgi application to run
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
This class MainPage uses a HTML template "index.html" for the rendering. Create the following file.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Todos</title>
<link rel="stylesheet" type="text/css" href="css/main.css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
</head>
<body>
<div style="width: 100%;">
<div class="topLine">
<div style="float: left;"><img src="images/todo.png" /></div>
<div style="float: left;" class="headline">Todos</div>
<div style="float: right;"><a href="{{ url }}">{{ url_linktext }}</a> {{user.nickname}}</div>
</div>
</div>
<div style="clear: both;"/>
{# Check if we have any todos, only in this case render the table #}
{% if numbertodos %}
You have a total number of {{numbertodos}} Todos.
<table>
<tr>
<th>Short description </th>
<th>Due Date</th>
<th>Long Description</th>
<th>URL</th>
<th>Created</th>
<th>Updated</th>
<th>Done</th>
<th>Send Email reminder</th>
</tr>
{% for todo in todos %}
<tr>
<td>
{{todo.shortDescription}}
</td>
<td>
{{todo.dueDate}}
</td>
<td>
{{todo.longDescription}}
</td>
<td>
{% if todo.url %}
<a href="{{todo.url}}" > {{todo.url}}</a>
{% endif %}
</td>
<td>
{{todo.created|date:"d.m.Y"}}
</td>
<td>
{{todo.updated|date:"d.m.Y"}}
</td>
<td>
<a class="done" href="/done?id={{todo.key.id}}" >Done</a>
</td>
<td>
<a class="email" href="/email?id={{todo.key.id}}" >Email</a>
</td>
</tr>
{% endfor %}
</table>
{% endif %}
<hr />
<div class="headline">Create new Todo?</div>
{% if user %}
<form action="/new" method="post">
<table>
<tr>
<td><label for="shortDescription">Summary</label></td>
<td><input type="text" name="shortDescription" id="shortDescriptions" size="80"/></td>
</tr>
<tr>
<td><label for="dueDate">Due Date</label></td>
<td><input type="dueDate" name="dueDate" id="dueDate"/></td>
</tr>
<tr>
<td valign="top"><label for="longDescription">Description</label></td>
<td><textarea rows="4" cols="80" name="longDescription" id="longDescription"></textarea></td>
</tr>
<tr>
<td><label for="url">URL</label></td>
<td><input type="text" name="url" id="url" size="80"/></td>
</tr>
<tr>
<td colspan="2" align="right"><input type="submit" value="Create"/></td>
</tr>
</table>
</form>
{% else %}
Login with your Google Account to create and review todos.
{% endif%}
</body>
</html>
Also create the directory css and put in this file "main.css". This is the style sheet used to make index.html "pretty".
body {
margin: 5px;
font-family: Arial, Helvetica, sans-serif;
}
hr {
border: 0;
background-color: #DDDDDD;
height: 1px;
margin: 5px;
}
table th {
background:#EFEFEF none repeat scroll 0 0;
border-top:1px solid #CCCCCC;
font-size:small;
padding-left:5px;
padding-right:4px;
padding-top:4px;
vertical-align:top;
text-align:left;
}
table tr {
background-color: #e5ecf9;
font-size:small;
}
.topLine {
height: 1.25em;
background-color: #e5ecf9;
padding-left: 4px;
padding-right: 4px;
padding-bottom: 3px;
padding-top: 2px;
}
.headline {
font-weight: bold;
color: #3366cc;
}
.done {
font-size: x-small;
vertical-align: top;
}
.email {
font-size: x-small;
vertical-align: top;
}
form td {
font-size: smaller;
}
Optional you can put a graphic "todo.png" into the images directory.
Switch to a command line. Switch to the directory which contains your application directory. Start your application locally with the following command.
dev_appserver.py googleappengine01/
Switch to a browser and access your local host via: http://localhost:8080/
The local installation will store your test data until you tell the engine to delete the test data. Use therefore the --clear_datastore option during startup.
dev_appserver.py --clear_datastore googleappengine01/
Now deploy your application to the Google cloud. Open the following URL http://appengine.google.com/ and login with your Google User. Press the button "Create an application".
You need then to verify your account via an SMS.
Create an application name. You have to choose one which is still available. After you found one you need to change the application in the app.yaml file to this new name.
Use now the command line to upload your application.
appcfg.py update googleappengine01/
Thats it. You should now be able to find your application at http://yourname.appspot.com/. For example this example can be found at http://myvogella.appspot.com/
You can also use Eclipse for developing GAE applications via the PyDev plugin.
Please see Python Development with Eclipse to learn how to install and use Eclipse and Pydev. The remaining focuses on the additional setup to use the GAE.
Create a Python project called "de.vogella.gae.python.todo". See Python Development with Eclipse for how to create a new Pydev / Python project in Eclipse.
Use Python version 2.5. Remember that the GAE does currently only support Python version 2.5
Copy the content of the directory from the previous example (all your files and directeries): todo.py, app.yam, index.html)into the source folder.

We need to add the GAE SDK to the pythonpath. Right click your project and select properties. Select PYTHONPATH and press "Add source folder" in the "External Source Folder". Select the installation directory of the GAE SDK. Also add lib/django, lib/webob and lib/yaml

You still can use the command line to run your GAE application. But we are now going to configure Eclipse to allow you to run your application directly from Eclipse.
Right click on "todo.py", select Run As -> Run Configuration. Under Main Module maintain the path to dev_appserver.py

Switch to the argument tab and maintain the full path name of your project as a parameter. Put the parameter in double-quotes.

Click run to start your application. If you have the console view open (Window -> Show View -> Console) you should see the familiar output of the GAE and be able to open the application in your browser as before.
Google provides a monitor application http://appengine.google.com/
Thank you for practicing with this tutorial.
I maintain this tutorial in my private time. If you like the information please help me by using flattr or donating or by
|
Before posting questions, please see the vogella FAQ . If you have questions or find an error in this article please use the www.vogella.de Google Group . I have created a short list how to create good questions which might also help you. .
http://www.vogella.de/articles/GoogleAppEngineJava/article.html Google App Engine Development with Java
http://code.google.com/intl/en/appengine Google App Engine
http://www.python.org/ Python Homepage
http://docs.python.org/ Python Documentation
http://www.djangoproject.com/documentation/0.96/templates/ Django template language