appengine/standard/memcache/guestbook/main.py (71 lines of code) (raw):

# Copyright 2015 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Sample application that demonstrates how to use the App Engine Memcache API. For more information, see README.md. """ # [START gae_memcache_guestbook_all] import cgi import cStringIO import logging import urllib from google.appengine.api import memcache from google.appengine.api import users from google.appengine.ext import ndb import webapp2 class Greeting(ndb.Model): """Models an individual Guestbook entry with author, content, and date.""" author = ndb.StringProperty() content = ndb.StringProperty() date = ndb.DateTimeProperty(auto_now_add=True) def guestbook_key(guestbook_name=None): """Constructs a Datastore key for a Guestbook entity with guestbook_name""" return ndb.Key("Guestbook", guestbook_name or "default_guestbook") class MainPage(webapp2.RequestHandler): def get(self): self.response.out.write("<html><body>") guestbook_name = self.request.get("guestbook_name") greetings = self.get_greetings(guestbook_name) stats = memcache.get_stats() self.response.write("<b>Cache Hits:{}</b><br>".format(stats["hits"])) self.response.write("<b>Cache Misses:{}</b><br><br>".format(stats["misses"])) self.response.write(greetings) self.response.write( """ <form action="/sign?{}" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form> <hr> <form>Guestbook name: <input value="{}" name="guestbook_name"> <input type="submit" value="switch"></form> </body> </html>""".format( urllib.urlencode({"guestbook_name": guestbook_name}), cgi.escape(guestbook_name), ) ) # [START gae_memcache_guestbook_check_memcache] def get_greetings(self, guestbook_name): """ get_greetings() Checks the cache to see if there are cached greetings. If not, call render_greetings and set the cache Args: guestbook_name: Guestbook entity group key (string). Returns: A string of HTML containing greetings. """ greetings = memcache.get("{}:greetings".format(guestbook_name)) if greetings is None: greetings = self.render_greetings(guestbook_name) try: added = memcache.add( "{}:greetings".format(guestbook_name), greetings, 10 ) if not added: logging.error("Memcache set failed.") except ValueError: logging.error("Memcache set failed - data larger than 1MB") return greetings # [END gae_memcache_guestbook_check_memcache] # [START gae_memcache_guestbook_query_datastore] def render_greetings(self, guestbook_name): """ render_greetings() Queries the database for greetings, iterate through the results and create the HTML. Args: guestbook_name: Guestbook entity group key (string). Returns: A string of HTML containing greetings """ greetings = ndb.gql( "SELECT * " "FROM Greeting " "WHERE ANCESTOR IS :1 " "ORDER BY date DESC LIMIT 10", guestbook_key(guestbook_name), ) output = cStringIO.StringIO() for greeting in greetings: if greeting.author: output.write("<b>{}</b> wrote:".format(greeting.author)) else: output.write("An anonymous person wrote:") output.write( "<blockquote>{}</blockquote>".format(cgi.escape(greeting.content)) ) return output.getvalue() # [END gae_memcache_guestbook_query_datastore] class Guestbook(webapp2.RequestHandler): def post(self): # We set the same parent key on the 'Greeting' to ensure each greeting # is in the same entity group. Queries across the single entity group # are strongly consistent. However, the write rate to a single entity # group is limited to ~1/second. guestbook_name = self.request.get("guestbook_name") greeting = Greeting(parent=guestbook_key(guestbook_name)) if users.get_current_user(): greeting.author = users.get_current_user().nickname() greeting.content = self.request.get("content") greeting.put() memcache.delete("{}:greetings".format(guestbook_name)) self.redirect("/?" + urllib.urlencode({"guestbook_name": guestbook_name})) app = webapp2.WSGIApplication([("/", MainPage), ("/sign", Guestbook)], debug=True) # [END gae_memcache_guestbook_all]