SlideShare una empresa de Scribd logo
1 de 30
Descargar para leer sin conexión
CS4HS
Using Google App Engine

Michael Parker
(michael.g.parker@gmail.com)
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
Outline
● Some background + DEMO!
● Building the app
○ Defining the data
○ Writing the server-side code
● Deployment + Conclusion
The Demo and
Some Other Stuff

Go to
http://cs4hs-tasklist.appspot.com
Start with a mock-up
Identify your data (nouns)
Identify your actions (verbs)
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>
The mock-up: showing/deleting tasks
<h3>Task list for mgp@google.com:</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>
Anatomy of a web application
Reading data:
1
HTTP GET /index.html
username=user@domain.com

Web
Server

2
Get tasks for
user@domain.com

/index.html
handler

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

3
/create.html
handler
/delete.html
handler

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

Storage
Anatomy of a web application
Modifying data (add, edit, delete):
2
1
HTTP POST /create.html
username=user@domain.com
title=title3, body=body3

Web
Server
/index.html
handler

Create task for
user@domain.com:
title=title3, body=body3

3

Get tasks for
mgp@google.com

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

/create.html
handler
/delete.html
handler

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

Storage
Defining and
Manipulating Data
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()
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()
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
Writing the
/index.html Handler
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)
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)
A look at template_values
{ "user": "mgp@google.com",
"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",
}
]
}
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>
...
The rendered output
<h3>Task list for mgp@google.com:</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>
...
Writing the
/create.html Handler
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')
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('/')
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)
A look at template_values
{ "user": "mgp@google.com",
"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": ...,
}
}
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>
Deployment and
Wrapping Up
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
Questions?

Más contenido relacionado

La actualidad más candente

The Many Ways to Build Modular JavaScript
The Many Ways to Build Modular JavaScriptThe Many Ways to Build Modular JavaScript
The Many Ways to Build Modular JavaScript
Tim Perry
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
moniguna
 

La actualidad más candente (20)

Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
ReactJs presentation
ReactJs presentationReactJs presentation
ReactJs presentation
 
VMWorld 2017 Hackathon training: Getting Started with Clarity
VMWorld 2017 Hackathon training: Getting Started with ClarityVMWorld 2017 Hackathon training: Getting Started with Clarity
VMWorld 2017 Hackathon training: Getting Started with Clarity
 
Grails Launchpad - From Ground Zero to Orbit
Grails Launchpad - From Ground Zero to OrbitGrails Launchpad - From Ground Zero to Orbit
Grails Launchpad - From Ground Zero to Orbit
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
J Query Presentation of David
J Query Presentation of DavidJ Query Presentation of David
J Query Presentation of David
 
Introduction to modern front-end with Vue.js
Introduction to modern front-end with Vue.jsIntroduction to modern front-end with Vue.js
Introduction to modern front-end with Vue.js
 
The Many Ways to Build Modular JavaScript
The Many Ways to Build Modular JavaScriptThe Many Ways to Build Modular JavaScript
The Many Ways to Build Modular JavaScript
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
 
Mini Curso de Django
Mini Curso de DjangoMini Curso de Django
Mini Curso de Django
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
 
Better web apps with React and Redux
Better web apps with React and ReduxBetter web apps with React and Redux
Better web apps with React and Redux
 
Unobtrusive JavaScript
Unobtrusive JavaScriptUnobtrusive JavaScript
Unobtrusive JavaScript
 
Ajax3
Ajax3Ajax3
Ajax3
 
Getting started with ReactJS
Getting started with ReactJSGetting started with ReactJS
Getting started with ReactJS
 
Switch to React.js from AngularJS developer
Switch to React.js from AngularJS developerSwitch to React.js from AngularJS developer
Switch to React.js from AngularJS developer
 
A (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesA (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project Files
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 

Similar a A To-do Web App on Google App Engine

Introduction to Backbone.js for Rails developers
Introduction to Backbone.js for Rails developersIntroduction to Backbone.js for Rails developers
Introduction to Backbone.js for Rails developers
AoteaStudios
 
Microsoft Offical Course 20410C_04
Microsoft Offical Course 20410C_04Microsoft Offical Course 20410C_04
Microsoft Offical Course 20410C_04
gameaxt
 
Tips and tricks for building api heavy ruby on rails applications
Tips and tricks for building api heavy ruby on rails applicationsTips and tricks for building api heavy ruby on rails applications
Tips and tricks for building api heavy ruby on rails applications
Tim Cull
 
Cloud Endpoints _Polymer_ Material design by Martin Görner
Cloud Endpoints_Polymer_Material design by Martin GörnerCloud Endpoints_Polymer_Material design by Martin Görner
Cloud Endpoints _Polymer_ Material design by Martin Görner
European Innovation Academy
 
20141001 delapsley-oc-openstack-final
20141001 delapsley-oc-openstack-final20141001 delapsley-oc-openstack-final
20141001 delapsley-oc-openstack-final
David Lapsley
 

Similar a A To-do Web App on Google App Engine (20)

D3_Tuto_GD
D3_Tuto_GDD3_Tuto_GD
D3_Tuto_GD
 
D3_Tuto_GD
D3_Tuto_GDD3_Tuto_GD
D3_Tuto_GD
 
Introduction to Backbone.js for Rails developers
Introduction to Backbone.js for Rails developersIntroduction to Backbone.js for Rails developers
Introduction to Backbone.js for Rails developers
 
Refresh Austin - Intro to Dexy
Refresh Austin - Intro to DexyRefresh Austin - Intro to Dexy
Refresh Austin - Intro to Dexy
 
Task scheduling in laravel 8 tutorial
Task scheduling in laravel 8 tutorialTask scheduling in laravel 8 tutorial
Task scheduling in laravel 8 tutorial
 
Writing HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAEWriting HTML5 Web Apps using Backbone.js and GAE
Writing HTML5 Web Apps using Backbone.js and GAE
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 
Experience Manager 6 Developer Features - Highlights
Experience Manager 6 Developer Features - HighlightsExperience Manager 6 Developer Features - Highlights
Experience Manager 6 Developer Features - Highlights
 
Microsoft Offical Course 20410C_04
Microsoft Offical Course 20410C_04Microsoft Offical Course 20410C_04
Microsoft Offical Course 20410C_04
 
Scott Guthrie at Dot Net Startup meetup
Scott Guthrie at Dot Net Startup meetupScott Guthrie at Dot Net Startup meetup
Scott Guthrie at Dot Net Startup meetup
 
Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016
Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016
Ajax on drupal the right way - DrupalCamp Campinas, São Paulo, Brazil 2016
 
Tips and tricks for building api heavy ruby on rails applications
Tips and tricks for building api heavy ruby on rails applicationsTips and tricks for building api heavy ruby on rails applications
Tips and tricks for building api heavy ruby on rails applications
 
Cloud Endpoints _Polymer_ Material design by Martin Görner
Cloud Endpoints_Polymer_Material design by Martin GörnerCloud Endpoints_Polymer_Material design by Martin Görner
Cloud Endpoints _Polymer_ Material design by Martin Görner
 
20141001 delapsley-oc-openstack-final
20141001 delapsley-oc-openstack-final20141001 delapsley-oc-openstack-final
20141001 delapsley-oc-openstack-final
 
Cloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload CourseCloudbase.io MoSync Reload Course
Cloudbase.io MoSync Reload Course
 
Creating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlCreating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-html
 
Aspnet mvc tutorial_01_cs
Aspnet mvc tutorial_01_csAspnet mvc tutorial_01_cs
Aspnet mvc tutorial_01_cs
 
Serverless archtiectures
Serverless archtiecturesServerless archtiectures
Serverless archtiectures
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Javascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JSJavascript Application Architecture with Backbone.JS
Javascript Application Architecture with Backbone.JS
 

Último

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Último (20)

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 

A To-do Web App on Google App Engine

  • 1. CS4HS Using Google App Engine Michael Parker (michael.g.parker@gmail.com)
  • 2. 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
  • 3. Outline ● Some background + DEMO! ● Building the app ○ Defining the data ○ Writing the server-side code ● Deployment + Conclusion
  • 4. The Demo and Some Other Stuff Go to http://cs4hs-tasklist.appspot.com
  • 5. Start with a mock-up
  • 8. 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>
  • 9. The mock-up: showing/deleting tasks <h3>Task list for mgp@google.com:</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>
  • 10. Anatomy of a web application Reading data: 1 HTTP GET /index.html username=user@domain.com Web Server 2 Get tasks for user@domain.com /index.html handler 4 <html> ... <li><h3>title1</h3>body1</li> <li><h3>title2</h3>body2</li> ... </html> 3 /create.html handler /delete.html handler task1: (title1, body1) task2: (title2, body2) Storage
  • 11. Anatomy of a web application Modifying data (add, edit, delete): 2 1 HTTP POST /create.html username=user@domain.com title=title3, body=body3 Web Server /index.html handler Create task for user@domain.com: title=title3, body=body3 3 Get tasks for mgp@google.com 5 <html> ... <li><h3>title1</h3>body1</li> <li><h3>title2</h3>body2</li> <li><h3>title3</h3>body3</li> ... </html> /create.html handler /delete.html handler 4 task1: (title1, body1) task2: (title2, body2) task3: (title3, body3) Storage
  • 13. 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()
  • 14. 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()
  • 15. 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
  • 17. 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)
  • 18. 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)
  • 19. A look at template_values { "user": "mgp@google.com", "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", } ] }
  • 20. 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> ...
  • 21. The rendered output <h3>Task list for mgp@google.com:</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> ...
  • 23. 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')
  • 24. 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('/')
  • 25. 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)
  • 26. A look at template_values { "user": "mgp@google.com", "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": ..., } }
  • 27. 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>
  • 29. 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