Download presentation
Presentation is loading. Please wait.
1
When are projects due? #infomgmtFAIL – This is why you never duplicate data. – Project 4 is Due To get it done in time you will need to work smart, cut corners, and adjust rapidly. – Use Rally's Burn-down charts to help you calibrate – Ask when >30mins of head-wall contact Asking is nice even if you figure it out yourself – It does NOT need to be a website/phone app/etc. Results > UX for project 4.
2
Prototype with Google App Engine Goal: Everyone gets to share one comment that is geotagged. Twitter-lite. Get set up: – http://code.google.com/appengine/downloads.html http://code.google.com/appengine/downloads.html – Everyone in your group!
3
Web services 101 Little "s" - bob Everything is an ACTION to a URL with some PARAMETERS http://yahoo.com/ – A "GET" to "/" with NO PARAMS http://www.google.com/search?q=Hello+World – A "GET" to "/search" with ONE param (URL encoded) of q="Hello World" … – POSTS you can't just type in the browser bar, but are normally form submits. Nice way to divide action from browsing. – Have a URL + a payload of name/value pairs (mostly) Also PUT, DELETE and HEAD, but who cares…
4
Google Datastore Stuff you don't need to know – "Paxos algorithm" – "ancestor queries" – High availability, entity groups, bla bla bla Stuff you do need to know – A little SQL – Basic idea of data types
5
Build application = webapp.WSGIApplication([ ('/', MainPage) #,('/sign', Guestbook) ], debug=True) def main(): run_wsgi_app(application) # http://pyfaq.infogami.com/tutor-what-is-if-name-main-forhttp://pyfaq.infogami.com/tutor-what-is-if-name-main-for if __name__ == '__main__': main()
6
User Management class MainPage(webapp.RequestHandler): def get(self): user = users.get_current_user() if user: self.response.headers['Content-Type'] = 'text/plain' self.response.out.write('Hello, ' + user.nickname()) else: self.redirect(users.create_login_url(self.request.uri)) This is so much nicer than debating with the architect if your users should be indexed by email address, or their user ID, or a unique 11 digit integer, or off their DB AUTO_INCREMENT ID, or… bla.
7
Knowing what was Posted def post(self): self.response.out.write(' You wrote: ') self.response.out.write( cgi.escape(self.request.get('content')) ) self.response.out.write(' ')
8
So what? Need to save it! class Tweet(db.Model): """Models an individual entry with an author, content, and date.""" author = db.UserProperty() content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) …so nice not to be writing SQL create statements. And DB modeling. And all the other overhead. A prototyper could get spoiled with this…
9
How to show a page of HTML? Annoying way – self.response.out.write(""" … Better way: path = os.path.join(os.path.dirname(__file__), 'index.html') self.response.out.write(template.render(path, template_values)) And every key in template_values maps to {{ key }}
10
Actually Saving It # Still figuring this "parent" thing out. bhill def tweetbucket_key(): """Constructs a datastore key for tweet entities""" return db.Key.from_path('Tweets', 'default_tweetbucket') def post(self): new_tweet = Tweet(parent=tweetbucket_key()) if users.get_current_user(): new_tweet.author = users.get_current_user() new_tweet.content = self.request.get('content') new_tweet.put()
11
Get back what you put in class AllPosts(webapp.RequestHandler): def get(self): tweets = db.GqlQuery("SELECT * " "FROM Tweet " "WHERE ANCESTOR IS :1 " "ORDER BY date DESC LIMIT 100", tweetbucket_key()) result = [] # simple array for tweet in tweets: result.append({ 'author':tweet.author.nickname(), 'content':tweet.content, 'date':tweet.date.isoformat() }) # simple object appended to array content = simplejson.dumps(result) if callback: # JSON-P in 2 lines. content = cgi.escape(callback) +"(" + content + ")" self.response.headers.add_header('content-type', 'application/json', charset='utf-8') self.response.out.write(content)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.