a to-do web app on google app engine

30
CS4HS Using Google App Engine Michael Parker ([email protected])

Upload: michael-parker

Post on 15-Jan-2015

236 views

Category:

Technology


0 download

DESCRIPTION

Presented to high school teachers participating in CS4HS. Covers writing simple to-do web app in Python on Google App Engine. 30 minutes with Q&A. Demo at http://cs4hs-tasklist.appspot.com/ Source code at https://github.com/mgp/cs4hs-tasklist

TRANSCRIPT

Page 1: A To-do Web App on Google App Engine

CS4HSUsing Google App Engine

Michael Parker([email protected])

Page 2: A To-do Web App on Google App Engine

So what is it?

What's it for?● Building and running web applications

Why use it?● Handles serving web pages, efficiently storing and retrieving

lots of data● Allows authenticating users, sending email and IMs,

downloading remote files● Easy management; don't need to buy or administer servers● Supports both Python and Java

Get the SDK at https://developers.google.com/appengine

Page 3: A To-do Web App on Google App Engine

Outline

●Some background + DEMO!●Building the app

○Defining the data○Writing the server-side code

●Deployment + Conclusion

Page 4: A To-do Web App on Google App Engine

The Demo andSome Other Stuff

Go tohttp://cs4hs-tasklist.appspot.com

Page 5: A To-do Web App on Google App Engine

Start with a mock-up

Page 6: A To-do Web App on Google App Engine

Identify your data (nouns)

Page 7: A To-do Web App on Google App Engine

Identify your actions (verbs)

Page 8: A To-do Web App on Google App Engine

The mock-up: creating a task

<h3>Add a new task:</h3> <form id="new_form" action="create" method="post"> Summary: <input type="text" name="summary" value="" /> Description: <textarea name="body" rows="5"></textarea> <input type="submit" value="Add Task" /> </form>

Page 9: A To-do Web App on Google App Engine

The mock-up: showing/deleting tasks

<h3>Task list for [email protected]:</h3> <form id="delete_form" action="delete" method="post"> <ul> <li> <input type="checkbox" name="task_id" value="task_id_1" /> <h4>make cs4hs slides</h4> <div>those will be the slides i'm presenting</div> </li> <li> <input type="checkbox" name="task_id" value="task_id_2" /> <h4>give presentation</h4> <div>hopefully to a thunderous applause</div> </li> </ul> <input type="submit" value="Delete Tasks" /></form>

Page 10: A To-do Web App on Google App Engine

Anatomy of a web application

Reading data:

Storage

HTTP GET /[email protected] Get tasks for

[email protected]

task1: (title1, body1)task2: (title2, body2)

<html> ...<li><h3>title1</h3>body1</li><li><h3>title2</h3>body2</li>... </html>

/index.html handler

/create.html handler

/delete.html handler

Web Server

1 2

34

Page 11: A To-do Web App on Google App Engine

Anatomy of a web application

Modifying data (add, edit, delete):

Storage

HTTP POST /[email protected]

title=title3, body=body3

Create task for [email protected]:

title=title3, body=body3

task1: (title1, body1)task2: (title2, body2)task3: (title3, body3)

<html> ...<li><h3>title1</h3>body1</li><li><h3>title2</h3>body2</li><li><h3>title3</h3>body3</li>... </html>

/index.html handler

/create.html handler

/delete.html handler

Web Server

Get tasks for [email protected]

12

3

45

Page 12: A To-do Web App on Google App Engine

Defining and Manipulating Data

Page 13: A To-do Web App on Google App Engine

Defining your data

Extend db.Model and define properties:

class Task(db.Model): """A saved task.""" creator = db.UserProperty() summary = db.StringProperty() body = db.TextProperty()

Page 14: A To-do Web App on Google App Engine

Inserting new data

Class db.Model provides a put method:

def NewTask(user, summary, body): """Creates a new task.

Arguments: user: The user who is creating the task. summary: A summary of the task. body: The full description of the task. """ task = Task() task.creator = user task.summary = summary task.body = body task.put()

Page 15: A To-do Web App on Google App Engine

Retrieving data

Add identifiers so they can be deleted later:

def GetTasks(user): """Returns all tasks created by the given user.

Arguments: The user to return tasks for. Returns: A list of tasks created by the given user. """ query = db.Query(Task) query.filter('creator =', user) tasks = query.fetch(1000) for task in tasks: task.id = str(task.key()) return tasks

Page 16: A To-do Web App on Google App Engine

Writing the/index.html Handler

Page 17: A To-do Web App on Google App Engine

Retrieving tasks

class GetTasksHandler(webapp.RequestHandler): """Displays all tasks for the user, and a form to enter a new task. """

def get(self): if users.GetCurrentUser() is None: login_url = users.CreateLoginURL(self.request.uri) self.redirect(login_url) else: write_html(self.response)

Page 18: A To-do Web App on Google App Engine

Retrieving tasks

def write_html(response, template_values={}): """Writes the tasks for the user in HTML.

Arguments: response: The connection to the user template_values: Any additional template values to render """ user = users.GetCurrentUser() user_tasks = tasks.GetTasks(user) template_values['user'] = user template_values['tasks'] = user_tasks rendered_page = template.render( _TEMPLATE_PATH, template_values) response.out.write(rendered_page)

Page 19: A To-do Web App on Google App Engine

A look at template_values

{ "user": "[email protected]", "tasks": [ { "id": "task_id_1", "summary": "make cs4hs slides", "body": "those will be the slides i'm presenting", }, { "id": "task_id_2", "summary": "give presentation", "body": "hopefully to a thunderous applause", } ]}

Page 20: A To-do Web App on Google App Engine

A look at the template

<h3>Task list for {{ user }}:</h3><form id="delete_form" action="delete" method="post"> <ul> {% for task in tasks %} <li> <input type="checkbox" name="task_id" value="{{ task.id }}" /> <h4>{{ task.summary }}</h4> <div>{{ task.body }}</div> </li> {% endfor %} </ul>

...

Page 21: A To-do Web App on Google App Engine

The rendered output

<h3>Task list for [email protected]:</h3><form id="delete_form" action="delete" method="post"> <ul> <li> <input type="checkbox" name="task_id" value="task_id_1" /> <h4>make cs4hs slides</h4> <div>those will be the slides i'm presenting</div> </li> <li> <input type="checkbox" name="task_id" value="task_id_2" /> <h4>give presentation</h4> <div>hopefully to a thunderous applause</div> </li> </ul> ...

Page 22: A To-do Web App on Google App Engine

Writing the/create.html Handler

Page 23: A To-do Web App on Google App Engine

Creating tasks

class NewTaskHandler(webapp.RequestHandler): """Handler that creates a new task."""

def post(self): user = users.GetCurrentUser() summary = self.request.get('summary') body = self.request.get('body') tasks.NewTask(user, summary, body) self.redirect('/index.html')

Page 24: A To-do Web App on Google App Engine

Creating tasks with error handling

class NewTaskHandler(webapp.RequestHandler): """Handler that creates a new task."""

def post(self): user = users.GetCurrentUser() summary = self.request.get('summary', None) body = self.request.get('body', None) if not summary or not body: self.handle_error(summary, body) return

tasks.NewTask(user, summary, body) self.redirect('/')

Page 25: A To-do Web App on Google App Engine

Creating tasks

...

def handle_error(self, summary, body): new_task_template_values = {} new_task_template_values['has_error'] = True if summary: new_task_template_values['summary'] = summary if body: new_task_template_values['body'] = body

template_values = {} template_values['new'] = new_task_template_values write_html(self.response, template_values)

Page 26: A To-do Web App on Google App Engine

A look at template_values

{ "user": "[email protected]", "tasks": [ { "id": "00001", "summary": "make cs4hs slides", "body": "those will be the slides i'm presenting", }, { "id": "00002", "summary": "give presentation", "body": "hopefully to a thunderous applause", } ], "new": { "has_error": True, "summary": ..., "body": ..., }}

Page 27: A To-do Web App on Google App Engine

A look at the template

<h3>Add a new task:</h3><form id="new_form" action="new" method="post"> {% if new.has_error %} <div class="error">Please enter both a summary and description below</div> {% endif %} Summary: <input type="text" name="summary" value="{{ new.summary }}" /> Description: <textarea name="body" rows="5">{{ new.body }}</textarea> <input type="submit" value="Add Task" /></form>

Page 28: A To-do Web App on Google App Engine

Deployment and Wrapping Up

Page 29: A To-do Web App on Google App Engine

Deployment

● Prerequisites:○ Download the SDK○ Get the code from https://github.com/mgp/cs4hs-tasklist○ Import project into GoogleAppEngineLauncher

● Running it locally:○ In GAELauncher, click Run, then Browse○ Data is stored on your hard drive○ Can edit the code without restarting the web server

● Deploying it to the web:○ Register the application name at http://appengine.google.

com○ Change application value in app.yaml to app name○ In GAELauncher, click Deploy○ See it at http://app-name.appspot.com

Page 30: A To-do Web App on Google App Engine

Questions?