SlideShare una empresa de Scribd logo
1 de 76
Descargar para leer sin conexión
Google App Engine in 40 Minutes

    (The Absolute Essentials)




   Paul Barry – Institute of Technology, Carlow in Ireland


                    PyCon Ireland 2011




                                                             2
Grab the slides:

http://paulbarry.itcarlow.ie/GAE.pdf
4
5
The Absolute Essentials in 40 Minutes...




                                           6
What is Google App Engine?




                             7
Cloud-based Application Deployment Environment




                                             8
Integrated Collection of Google APIs




                                       9
Guido's Playground




                     10
Is App Engine “just another framework”?




                                          11
It is all about your data...




                               12
Think of App Engine as a highly scalable,
distributed database server that you can program
                 with Python 2.5...




                                               13
Think of App Engine as a highly scalable,
distributed database server that you can program
                 with Python 2.5...

   and (cough) Java and (cough, cough) Go




                                               14
MVC

      15
Let's solve a real problem...




                                16
17
18
19
20
Step 1


        Download the SDK from:

  http://code.google.com/appengine/

and sign-up for an App Engine account ID



                                           21
Step 2



Create a new project...




                          22
...by creating an app.yaml file

      application: dwwgapp
      version: 1
      runtime: python
      api_version: 1

      handlers:
      - url: /static
        static_dir: static

      - url: /.*
        script: dwwgapp.py
                                  23
Step 3


Model Your Data




                  24
Create dwwgDB.py (1 of 3)
from google.appengine.ext import db




                                      25
Create dwwgDB.py (2 of 3)
from google.appengine.ext import db

class Sighting(db.Model):




                                      26
27
Create dwwgDB.py (3 of 3)
from google.appengine.ext import db

class Sighting(db.Model):
   name = db.StringProperty()
   email = db.StringProperty()
   date = db.DateProperty()
   time = db.TimeProperty()
   location = db.StringProperty()
   fin_type = db.StringProperty()
   whale_type = db.StringProperty()
   blow_type = db.StringProperty()
   wave_type = db.StringProperty()
                                      28
Step 4


Define your UI in HTML




                         29
The header.html template


<html>
   <head>
       <title>{{ title }}</title>
   </head>
   <body>
       <h1>{{ title }}</h1>



                                    30
The footer.html template




       <p> {{ links }} </p>
   </body>
</html>




                                  31
The form_start.html template




<form method=”POST” action=”/”>
   <table>




                                   32
The form_end.html


       <tr><th>&nbsp;</th>
          <td><input type="submit"
               value="{{ sub_title }}"></td>
       </tr>
   </table>
</form>



                                          33
Render some HTML



from google.appengine.ext.webapp import template

html = template.render('templates/header.html',
          {'title': 'Report a Possible Sighting'})




                                                   34
Rendering a Page

from google.appengine.ext.webapp import template


html = template.render('templates/header.html',
                             {'title': 'Report a Possible Sighting'})
html = html + template.render('templates/form_start.html', {})

# Do something in here to render the form?!?!?!?!?!?!?

html = html + template.render('templates/form_end.html',
                                    {'sub_title': 'Submit Sighting'})
html = html + template.render('templates/footer.html', {'links': ''})




                                                                  35
Step 5




Write code to render your form




                                 36
Django Forms to the Rescue!


from google.appengine.ext.db import djangoforms

import dwwgDB

class SightingForm(djangoforms.ModelForm):
    class Meta:
        model = dwwgDB.Sighting




                                                  37
Rendering a Page, Again

from google.appengine.ext.webapp import template


html = template.render('templates/header.html',
                             {'title': 'Report a Possible Sighting'})
html = html + template.render('templates/form_start.html', {})

html = html + str(SightingForm())

html = html + template.render('templates/form_end.html',
                                    {'sub_title': 'Submit Sighting'})
html = html + template.render('templates/footer.html', {'links': ''})




                                                                  38
Step 6


Tie it all together with logic




                                 39
You need to start your webapp

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


   …



app = webapp.WSGIApplication([('/.*', SightingInputPage)], debug=True)

def main():
    run_wsgi_app(app)

if __name__ == '__main__':
    main()



                                                                  40
Remember the app.yaml file?

     application: dwwgapp
     version: 1
     runtime: python
     api_version: 1

     handlers:
     - url: /static
       static_dir: static

     - url: /.*
       script: dwwgapp.py
                              41
Put this code in dwwgapp.py

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


   …



app = webapp.WSGIApplication([('/.*', SightingInputPage)], debug=True)

def main():
    run_wsgi_app(app)

if __name__ == '__main__':
    main()



                                                                  42
What's this SightingInputPage thing?




                                       43
Responding to a GET Request


class SightingInputPage(webapp.RequestHandler):
    def get(self):
        html = template.render('templates/header.html',
                                 {'title': 'Report a Possible Sighting'})
        html = html + template.render('templates/form_start.html', {})
        html = html + str(SightingForm())
        html = html + template.render('templates/form_end.html',
                                         {'sub_title': 'Submit Sighting'})
        html = html + template.render('templates/footer.html', {'links': ''})
        self.response.out.write(html)




                                                                           44
Step 7




Take your local app for a spin




                                 45
Click the “Run” button...




            or

$ dev_appserver.py dwwgapp   46
Ta Da! :-(




             47
Looks kinda shitty, doesn't it?




                                  48
Add a little CSS goodness..




<link type="text/css" rel="stylesheet" href="/static/dwwg.css" />
<link type="text/css" rel="stylesheet" href="/static/styledform.css" />




                                                                  49
...and some code to dwwgDB.py


_FINS =   ['Falcate', 'Triangular', 'Rounded']
_WHALES = ['Humpback', 'Orca', 'Blue', 'Killer', 'Beluga', 'Fin', 'Gray', 'Sperm']
_BLOWS = ['Tall', 'Bushy', 'Dense']
_WAVES = ['Flat', 'Small', 'Moderate', 'Large', 'Breaking', 'High']

      ...

location =    db.StringProperty(multiline=True)
fin_type =   db.StringProperty(choices=_FINS)
whale_type = db.StringProperty(choices=_WHALES)
blow_type = db.StringProperty(choices=_BLOWS)
wave_type = db.StringProperty(choices=_WAVES)




                                                                                     50
Ta Da! :-)




             51
Step 8




Do something with your data




                              52
You need to POST data!




   POST data with put()




                          53
class SightingInputPage(webapp.RequestHandler):
    def get(self):
        html = template.render('templates/header.html',
                                 {'title': 'Report a Possible Sighting'})
        html = html + template.render('templates/form_start.html', {})
        html = html + str(SightingForm())
        html = html + template.render('templates/form_end.html',
                                         {'sub_title': 'Submit Sighting'})
        html = html + template.render('templates/footer.html', {'links': ''})
        self.response.out.write(html)




                                                                           54
class SightingInputPage(webapp.RequestHandler):
    def get(self):
        html = template.render('templates/header.html',
                                 {'title': 'Report a Possible Sighting'})
        html = html + template.render('templates/form_start.html', {})
        html = html + str(SightingForm())
        html = html + template.render('templates/form_end.html',
                                         {'sub_title': 'Submit Sighting'})
        html = html + template.render('templates/footer.html', {'links': ''})
        self.response.out.write(html)


   def post(self):




                                                                           55
class SightingInputPage(webapp.RequestHandler):
    def get(self):
        html = template.render('templates/header.html',
                                 {'title': 'Report a Possible Sighting'})
        html = html + template.render('templates/form_start.html', {})
        html = html + str(SightingForm())
        html = html + template.render('templates/form_end.html',
                                         {'sub_title': 'Submit Sighting'})
        html = html + template.render('templates/footer.html', {'links': ''})
        self.response.out.write(html)


   def post(self):
       new_sighting = dwwgDB.Sighting()




                                                                           56
class SightingInputPage(webapp.RequestHandler):
    def get(self):
        html = template.render('templates/header.html',
                                 {'title': 'Report a Possible Sighting'})
        html = html + template.render('templates/form_start.html', {})
        html = html + str(SightingForm())
        html = html + template.render('templates/form_end.html',
                                         {'sub_title': 'Submit Sighting'})
        html = html + template.render('templates/footer.html', {'links': ''})
        self.response.out.write(html)


   def post(self):
       new_sighting = dwwgDB.Sighting()
       new_sighting.name = self.request.get('name')
       new_sighting.email = self.request.get('email')
       new_sighting.date = self.request.get('date')
       new_sighting.time = self.request.get('time')
       new_sighting.location = self.request.get('location')
       new_sighting.fin_type = self.request.get('fin_type')
       new_sighting.whale_type = self.request.get('whale_type')
       new_sighting.blow_type =self.request.get('blow_type')
       new_sighting.wave_type = self.request.get('wave_type')




                                                                           57
class SightingInputPage(webapp.RequestHandler):
    def get(self):
        html = template.render('templates/header.html',
                                 {'title': 'Report a Possible Sighting'})
        html = html + template.render('templates/form_start.html', {})
        html = html + str(SightingForm())
        html = html + template.render('templates/form_end.html',
                                         {'sub_title': 'Submit Sighting'})
        html = html + template.render('templates/footer.html', {'links': ''})
        self.response.out.write(html)


   def post(self):
       new_sighting = dwwgDB.Sighting()
       new_sighting.name = self.request.get('name')
       new_sighting.email = self.request.get('email')
       new_sighting.date = self.request.get('date')
       new_sighting.time = self.request.get('time')
       new_sighting.location = self.request.get('location')
       new_sighting.fin_type = self.request.get('fin_type')
       new_sighting.whale_type = self.request.get('whale_type')
       new_sighting.blow_type =self.request.get('blow_type')
       new_sighting.wave_type = self.request.get('wave_type')

       new_sighting.put()

                                                                           58
And don't forget to say “Thanks!”


html = template.render('templates/header.html', {'title': 'Thank you!'})
html = html + "<p>Thank you for providing your sighting data.</p>"
html = html + template.render('templates/footer.html',
                      {'links': 'Enter <a href="/">another sighting</a>.'})

self.response.out.write(html)




                                                                         59
60
Step 9




Deploy to Google's cloud




                           61
Click the “Deploy” button...




             or

$ appcfg.py upload dwwgapp/    62
http://dwwgapp.appspot.com




                             63
Step 10




Realise your not done...




                           64
Damn That Spam!




Some smart-alec posted a sighting
of a Great White Shark on the top
       of Mount Leinster...




                                    65
What to do?




              66
A tiny config tweak to app.yaml...
       application: dwwgapp
       version: 1
       runtime: python
       api_version: 1

       handlers:
       - url: /static
         static_dir: static

       - url: /.*
         script: dwwgapp.py
         login: required
                                     67
...and two tiny code changes

       Add this to the dwwgDB.py model:
          which_user = db.UserProperty()




Add this to your post() method in dwwgapp.py:

new_sighting.which_user = users.get_current_user()


                                                68
http://dwwgapp.appspot.com




                             69
http://appengine.google.com




                              70
And after all that,
what do you end up with?




                           71
Happy Clients!




                 72
Want to learn more
about this talk's example code?




                                  73
Head First Python




                    74
Don't forget to check out
the App Engine Tutorial on Sunday
        with Seán Murphy




                                    75
76

Más contenido relacionado

La actualidad más candente

SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterHaehnchen
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesCiaranMcNulty
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4Javier Eguiluz
 
Leaving Interface Builder Behind
Leaving Interface Builder BehindLeaving Interface Builder Behind
Leaving Interface Builder BehindJohn Wilker
 
Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptmartinlippert
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesRainer Stropek
 
Asp netmvc e03
Asp netmvc e03Asp netmvc e03
Asp netmvc e03Yu GUAN
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fabio Akita
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con djangoTomás Henríquez
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND Enrique Oriol Bermúdez
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS InternalEyal Vardi
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSNicolas Embleton
 
Styling recipes for Angular components
Styling recipes for Angular componentsStyling recipes for Angular components
Styling recipes for Angular componentsNir Kaufman
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 

La actualidad más candente (16)

SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4
 
Leaving Interface Builder Behind
Leaving Interface Builder BehindLeaving Interface Builder Behind
Leaving Interface Builder Behind
 
Why SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScriptWhy SOLID matters - even for JavaScript
Why SOLID matters - even for JavaScript
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
 
Asp netmvc e03
Asp netmvc e03Asp netmvc e03
Asp netmvc e03
 
Nativescript angular
Nativescript angularNativescript angular
Nativescript angular
 
Angular Workshop FrOSCon 2018
Angular Workshop  FrOSCon 2018Angular Workshop  FrOSCon 2018
Angular Workshop FrOSCon 2018
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
 
Styling recipes for Angular components
Styling recipes for Angular componentsStyling recipes for Angular components
Styling recipes for Angular components
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 

Destacado

What's the Scoop with Python 3?
What's the Scoop with Python 3?What's the Scoop with Python 3?
What's the Scoop with Python 3?Python Ireland
 
Python Ireland - Who, how, what
Python Ireland - Who, how, whatPython Ireland - Who, how, what
Python Ireland - Who, how, whatPython Ireland
 
Cloud by Numbers
Cloud by NumbersCloud by Numbers
Cloud by NumbersJosh Holmes
 
Introduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersIntroduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersPython Ireland
 
Best And Worst Practices Building Ria with Adobe and Microsoft
Best And Worst Practices Building Ria with Adobe and MicrosoftBest And Worst Practices Building Ria with Adobe and Microsoft
Best And Worst Practices Building Ria with Adobe and MicrosoftJosh Holmes
 

Destacado (6)

What's the Scoop with Python 3?
What's the Scoop with Python 3?What's the Scoop with Python 3?
What's the Scoop with Python 3?
 
Python Ireland - Who, how, what
Python Ireland - Who, how, whatPython Ireland - Who, how, what
Python Ireland - Who, how, what
 
Lambada
LambadaLambada
Lambada
 
Cloud by Numbers
Cloud by NumbersCloud by Numbers
Cloud by Numbers
 
Introduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersIntroduction to Erlang for Python Programmers
Introduction to Erlang for Python Programmers
 
Best And Worst Practices Building Ria with Adobe and Microsoft
Best And Worst Practices Building Ria with Adobe and MicrosoftBest And Worst Practices Building Ria with Adobe and Microsoft
Best And Worst Practices Building Ria with Adobe and Microsoft
 

Similar a Google App Engine in 40 minutes (the absolute essentials)

Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJoaquim Rocha
 
Gae Meets Django
Gae Meets DjangoGae Meets Django
Gae Meets Djangofool2nd
 
A gentle intro to the Django Framework
A gentle intro to the Django FrameworkA gentle intro to the Django Framework
A gentle intro to the Django FrameworkRicardo Soares
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS ArchitectureEyal Vardi
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsAdégòkè Obasá
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJames Casey
 
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 2010ikailan
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineYared Ayalew
 
How to Webpack your Django!
How to Webpack your Django!How to Webpack your Django!
How to Webpack your Django!David Gibbons
 
Working With The Symfony Admin Generator
Working With The Symfony Admin GeneratorWorking With The Symfony Admin Generator
Working With The Symfony Admin GeneratorJohn Cleveley
 
A Basic Django Introduction
A Basic Django IntroductionA Basic Django Introduction
A Basic Django IntroductionGanga Ram
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileGlobalLogic Ukraine
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2Paras Mendiratta
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4DEVCON
 

Similar a Google App Engine in 40 minutes (the absolute essentials) (20)

Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Gae Meets Django
Gae Meets DjangoGae Meets Django
Gae Meets Django
 
A gentle intro to the Django Framework
A gentle intro to the Django FrameworkA gentle intro to the Django Framework
A gentle intro to the Django Framework
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
 
IndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web AppsIndexedDB and Push Notifications in Progressive Web Apps
IndexedDB and Push Notifications in Progressive Web Apps
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Django quickstart
Django quickstartDjango quickstart
Django quickstart
 
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
 
Introduction to angular js
Introduction to angular jsIntroduction to angular js
Introduction to angular js
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
How to Webpack your Django!
How to Webpack your Django!How to Webpack your Django!
How to Webpack your Django!
 
Django crush course
Django crush course Django crush course
Django crush course
 
Working With The Symfony Admin Generator
Working With The Symfony Admin GeneratorWorking With The Symfony Admin Generator
Working With The Symfony Admin Generator
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
A Basic Django Introduction
A Basic Django IntroductionA Basic Django Introduction
A Basic Django Introduction
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobile
 
Django
DjangoDjango
Django
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4
 

Más de Python Ireland

Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati Python Ireland
 
Object Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonObject Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonPython Ireland
 
Web-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using PythonWeb-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using PythonPython Ireland
 
Utopia Kingdoms scaling case. From 4 users to 50.000+
Utopia Kingdoms scaling case. From 4 users to 50.000+Utopia Kingdoms scaling case. From 4 users to 50.000+
Utopia Kingdoms scaling case. From 4 users to 50.000+Python Ireland
 
The Larch - a visual interactive programming environment
The Larch - a visual interactive programming environmentThe Larch - a visual interactive programming environment
The Larch - a visual interactive programming environmentPython Ireland
 
Python vs JLizard.... a python logging experience
Python vs JLizard.... a python logging experiencePython vs JLizard.... a python logging experience
Python vs JLizard.... a python logging experiencePython Ireland
 
Python Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - AppenginePython Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - AppenginePython Ireland
 
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...Python Ireland
 
Python Ireland Nov 2010 Talk: Unit Testing
Python Ireland Nov 2010 Talk: Unit TestingPython Ireland Nov 2010 Talk: Unit Testing
Python Ireland Nov 2010 Talk: Unit TestingPython Ireland
 
Python Ireland Nov 2010 - RESTing with Django
Python Ireland Nov 2010 - RESTing with DjangoPython Ireland Nov 2010 - RESTing with Django
Python Ireland Nov 2010 - RESTing with DjangoPython Ireland
 
Python Ireland Feb '11 Talks: Introduction to Python
Python Ireland Feb '11 Talks: Introduction to PythonPython Ireland Feb '11 Talks: Introduction to Python
Python Ireland Feb '11 Talks: Introduction to PythonPython Ireland
 
Python Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
Python Ireland Dec Talks - Windows Azure -- The Nuts and BoltsPython Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
Python Ireland Dec Talks - Windows Azure -- The Nuts and BoltsPython Ireland
 
Python for cloud computing
Python for cloud computingPython for cloud computing
Python for cloud computingPython Ireland
 
IPython: The awesome python shell
IPython: The awesome python shellIPython: The awesome python shell
IPython: The awesome python shellPython Ireland
 
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
[Python Ireland] Cocoa and the Python/C API by Rory GeogheganPython Ireland
 

Más de Python Ireland (17)

Async I/O in Python
Async I/O in PythonAsync I/O in Python
Async I/O in Python
 
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
Python Ireland 2012 - Message brokers and Python by Fernando Ciciliati
 
Object Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in PythonObject Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in Python
 
Web-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using PythonWeb-service based Mobile Geospatial Application Development using Python
Web-service based Mobile Geospatial Application Development using Python
 
Utopia Kingdoms scaling case. From 4 users to 50.000+
Utopia Kingdoms scaling case. From 4 users to 50.000+Utopia Kingdoms scaling case. From 4 users to 50.000+
Utopia Kingdoms scaling case. From 4 users to 50.000+
 
The Larch - a visual interactive programming environment
The Larch - a visual interactive programming environmentThe Larch - a visual interactive programming environment
The Larch - a visual interactive programming environment
 
Python vs JLizard.... a python logging experience
Python vs JLizard.... a python logging experiencePython vs JLizard.... a python logging experience
Python vs JLizard.... a python logging experience
 
Vim and Python
Vim and PythonVim and Python
Vim and Python
 
Python Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - AppenginePython Ireland Nov 2009 Talk - Appengine
Python Ireland Nov 2009 Talk - Appengine
 
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
Python Ireland May 2011 - What is Pyramid and where is it with respect to Dja...
 
Python Ireland Nov 2010 Talk: Unit Testing
Python Ireland Nov 2010 Talk: Unit TestingPython Ireland Nov 2010 Talk: Unit Testing
Python Ireland Nov 2010 Talk: Unit Testing
 
Python Ireland Nov 2010 - RESTing with Django
Python Ireland Nov 2010 - RESTing with DjangoPython Ireland Nov 2010 - RESTing with Django
Python Ireland Nov 2010 - RESTing with Django
 
Python Ireland Feb '11 Talks: Introduction to Python
Python Ireland Feb '11 Talks: Introduction to PythonPython Ireland Feb '11 Talks: Introduction to Python
Python Ireland Feb '11 Talks: Introduction to Python
 
Python Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
Python Ireland Dec Talks - Windows Azure -- The Nuts and BoltsPython Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
Python Ireland Dec Talks - Windows Azure -- The Nuts and Bolts
 
Python for cloud computing
Python for cloud computingPython for cloud computing
Python for cloud computing
 
IPython: The awesome python shell
IPython: The awesome python shellIPython: The awesome python shell
IPython: The awesome python shell
 
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
[Python Ireland] Cocoa and the Python/C API by Rory Geoghegan
 

Último

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 

Último (20)

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 

Google App Engine in 40 minutes (the absolute essentials)

  • 1.
  • 2. Google App Engine in 40 Minutes (The Absolute Essentials) Paul Barry – Institute of Technology, Carlow in Ireland PyCon Ireland 2011 2
  • 4. 4
  • 5. 5
  • 6. The Absolute Essentials in 40 Minutes... 6
  • 7. What is Google App Engine? 7
  • 9. Integrated Collection of Google APIs 9
  • 11. Is App Engine “just another framework”? 11
  • 12. It is all about your data... 12
  • 13. Think of App Engine as a highly scalable, distributed database server that you can program with Python 2.5... 13
  • 14. Think of App Engine as a highly scalable, distributed database server that you can program with Python 2.5... and (cough) Java and (cough, cough) Go 14
  • 15. MVC 15
  • 16. Let's solve a real problem... 16
  • 17. 17
  • 18. 18
  • 19. 19
  • 20. 20
  • 21. Step 1 Download the SDK from: http://code.google.com/appengine/ and sign-up for an App Engine account ID 21
  • 22. Step 2 Create a new project... 22
  • 23. ...by creating an app.yaml file application: dwwgapp version: 1 runtime: python api_version: 1 handlers: - url: /static static_dir: static - url: /.* script: dwwgapp.py 23
  • 24. Step 3 Model Your Data 24
  • 25. Create dwwgDB.py (1 of 3) from google.appengine.ext import db 25
  • 26. Create dwwgDB.py (2 of 3) from google.appengine.ext import db class Sighting(db.Model): 26
  • 27. 27
  • 28. Create dwwgDB.py (3 of 3) from google.appengine.ext import db class Sighting(db.Model): name = db.StringProperty() email = db.StringProperty() date = db.DateProperty() time = db.TimeProperty() location = db.StringProperty() fin_type = db.StringProperty() whale_type = db.StringProperty() blow_type = db.StringProperty() wave_type = db.StringProperty() 28
  • 29. Step 4 Define your UI in HTML 29
  • 30. The header.html template <html> <head> <title>{{ title }}</title> </head> <body> <h1>{{ title }}</h1> 30
  • 31. The footer.html template <p> {{ links }} </p> </body> </html> 31
  • 32. The form_start.html template <form method=”POST” action=”/”> <table> 32
  • 33. The form_end.html <tr><th>&nbsp;</th> <td><input type="submit" value="{{ sub_title }}"></td> </tr> </table> </form> 33
  • 34. Render some HTML from google.appengine.ext.webapp import template html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) 34
  • 35. Rendering a Page from google.appengine.ext.webapp import template html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) # Do something in here to render the form?!?!?!?!?!?!? html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) 35
  • 36. Step 5 Write code to render your form 36
  • 37. Django Forms to the Rescue! from google.appengine.ext.db import djangoforms import dwwgDB class SightingForm(djangoforms.ModelForm): class Meta: model = dwwgDB.Sighting 37
  • 38. Rendering a Page, Again from google.appengine.ext.webapp import template html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) 38
  • 39. Step 6 Tie it all together with logic 39
  • 40. You need to start your webapp from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app … app = webapp.WSGIApplication([('/.*', SightingInputPage)], debug=True) def main(): run_wsgi_app(app) if __name__ == '__main__': main() 40
  • 41. Remember the app.yaml file? application: dwwgapp version: 1 runtime: python api_version: 1 handlers: - url: /static static_dir: static - url: /.* script: dwwgapp.py 41
  • 42. Put this code in dwwgapp.py from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app … app = webapp.WSGIApplication([('/.*', SightingInputPage)], debug=True) def main(): run_wsgi_app(app) if __name__ == '__main__': main() 42
  • 44. Responding to a GET Request class SightingInputPage(webapp.RequestHandler): def get(self): html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) self.response.out.write(html) 44
  • 45. Step 7 Take your local app for a spin 45
  • 46. Click the “Run” button... or $ dev_appserver.py dwwgapp 46
  • 48. Looks kinda shitty, doesn't it? 48
  • 49. Add a little CSS goodness.. <link type="text/css" rel="stylesheet" href="/static/dwwg.css" /> <link type="text/css" rel="stylesheet" href="/static/styledform.css" /> 49
  • 50. ...and some code to dwwgDB.py _FINS = ['Falcate', 'Triangular', 'Rounded'] _WHALES = ['Humpback', 'Orca', 'Blue', 'Killer', 'Beluga', 'Fin', 'Gray', 'Sperm'] _BLOWS = ['Tall', 'Bushy', 'Dense'] _WAVES = ['Flat', 'Small', 'Moderate', 'Large', 'Breaking', 'High'] ... location = db.StringProperty(multiline=True) fin_type = db.StringProperty(choices=_FINS) whale_type = db.StringProperty(choices=_WHALES) blow_type = db.StringProperty(choices=_BLOWS) wave_type = db.StringProperty(choices=_WAVES) 50
  • 52. Step 8 Do something with your data 52
  • 53. You need to POST data! POST data with put() 53
  • 54. class SightingInputPage(webapp.RequestHandler): def get(self): html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) self.response.out.write(html) 54
  • 55. class SightingInputPage(webapp.RequestHandler): def get(self): html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) self.response.out.write(html) def post(self): 55
  • 56. class SightingInputPage(webapp.RequestHandler): def get(self): html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) self.response.out.write(html) def post(self): new_sighting = dwwgDB.Sighting() 56
  • 57. class SightingInputPage(webapp.RequestHandler): def get(self): html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) self.response.out.write(html) def post(self): new_sighting = dwwgDB.Sighting() new_sighting.name = self.request.get('name') new_sighting.email = self.request.get('email') new_sighting.date = self.request.get('date') new_sighting.time = self.request.get('time') new_sighting.location = self.request.get('location') new_sighting.fin_type = self.request.get('fin_type') new_sighting.whale_type = self.request.get('whale_type') new_sighting.blow_type =self.request.get('blow_type') new_sighting.wave_type = self.request.get('wave_type') 57
  • 58. class SightingInputPage(webapp.RequestHandler): def get(self): html = template.render('templates/header.html', {'title': 'Report a Possible Sighting'}) html = html + template.render('templates/form_start.html', {}) html = html + str(SightingForm()) html = html + template.render('templates/form_end.html', {'sub_title': 'Submit Sighting'}) html = html + template.render('templates/footer.html', {'links': ''}) self.response.out.write(html) def post(self): new_sighting = dwwgDB.Sighting() new_sighting.name = self.request.get('name') new_sighting.email = self.request.get('email') new_sighting.date = self.request.get('date') new_sighting.time = self.request.get('time') new_sighting.location = self.request.get('location') new_sighting.fin_type = self.request.get('fin_type') new_sighting.whale_type = self.request.get('whale_type') new_sighting.blow_type =self.request.get('blow_type') new_sighting.wave_type = self.request.get('wave_type') new_sighting.put() 58
  • 59. And don't forget to say “Thanks!” html = template.render('templates/header.html', {'title': 'Thank you!'}) html = html + "<p>Thank you for providing your sighting data.</p>" html = html + template.render('templates/footer.html', {'links': 'Enter <a href="/">another sighting</a>.'}) self.response.out.write(html) 59
  • 60. 60
  • 61. Step 9 Deploy to Google's cloud 61
  • 62. Click the “Deploy” button... or $ appcfg.py upload dwwgapp/ 62
  • 64. Step 10 Realise your not done... 64
  • 65. Damn That Spam! Some smart-alec posted a sighting of a Great White Shark on the top of Mount Leinster... 65
  • 67. A tiny config tweak to app.yaml... application: dwwgapp version: 1 runtime: python api_version: 1 handlers: - url: /static static_dir: static - url: /.* script: dwwgapp.py login: required 67
  • 68. ...and two tiny code changes Add this to the dwwgDB.py model: which_user = db.UserProperty() Add this to your post() method in dwwgapp.py: new_sighting.which_user = users.get_current_user() 68
  • 71. And after all that, what do you end up with? 71
  • 73. Want to learn more about this talk's example code? 73
  • 75. Don't forget to check out the App Engine Tutorial on Sunday with Seán Murphy 75
  • 76. 76