Comment out the 'loadtest' backend in the 'counter' backend sample so that it does...
[gae-samples.git] / paging / suggestunique.py
blobbc509e84cf8e19b25ca6a9196d36d457feaf7c52
1 #!/usr/bin/env python
3 # Copyright 2008 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 """Suggestion Box - An example paging application.
20 A simple Suggestion Box application that demonstrates
21 paging by creating a unique value for each suggestion. The
22 uniqueness is created by sharding counters across
23 all the users of the system.
25 """
27 import datetime
28 import hashlib
29 import os
30 import wsgiref.handlers
32 from google.appengine.ext import webapp
33 from google.appengine.ext.webapp import template
34 from google.appengine.ext import db
35 from google.appengine.api import users
36 from google.appengine.ext.webapp.util import login_required
37 from google.appengine.ext.webapp.util import run_wsgi_app
40 PAGESIZE = 5
43 class Contributor (db.Model):
44 """
45 Contributors are stored with a key of the users email
46 address. The 'count' is used as a per user
47 counter that is incremented each time a user
48 adds a Suggestion and is used to generate a unique
49 property value 'Suggestion.when' that allows paging
50 over suggestions in creation order.
51 """
52 count = db.IntegerProperty(default=0)
55 class Suggestion(db.Model):
56 """
57 A suggestion in the suggestion box, which we want to display
58 in the order they were created.
59 """
60 suggestion = db.StringProperty()
61 created = db.DateTimeProperty(auto_now_add=True)
62 when = db.StringProperty()
65 def _unique_user(user):
66 """
67 Creates a unique string by using an increasing
68 counter sharded per user. The resulting string
69 is hashed to keep the users email address private.
71 Args:
72 The currently logged in user.
74 Returns:
75 A hashed unique value based on the user
76 and the associated incremented Contributor.count.
77 """
78 email = user.email()
80 def txn():
81 contributor = Contributor.get_by_key_name(email)
82 if contributor == None:
83 contributor = Contributor(key_name=email)
84 contributor.count += 1
85 contributor.put()
86 return contributor.count
88 count = db.run_in_transaction(txn)
90 return hashlib.md5(email + '|' + str(count)).hexdigest()
93 def whenfromcreated(created):
94 """
95 Create a unique 'when' property value based on the
96 time the entity was created.
98 Args:
99 created: datetime the entity was created.
101 Returns:
102 A unique value that will be ordered by
103 entity creation time.
105 return created.isoformat()[0:19] + '|' + _unique_user(users.get_current_user())
108 class SuggestionHandler(webapp.RequestHandler):
110 Handles the creation of a single Suggestion, and the display
111 of suggestions broken into PAGESIZE pages.
114 @login_required
115 def get(self):
116 bookmark = self.request.get('bookmark')
117 next = None
118 if bookmark:
119 query = Suggestion.gql('WHERE when <= :bookmark ORDER BY when DESC',
120 bookmark=bookmark)
121 suggestions = query.fetch(PAGESIZE+1)
122 else:
123 suggestions = Suggestion.gql('ORDER BY when DESC').fetch(PAGESIZE+1)
124 if len(suggestions) == PAGESIZE+1:
125 next = suggestions[-1].when
126 suggestions = suggestions[:PAGESIZE]
128 template_values = {'next': next, 'suggestions': suggestions}
129 template_file = os.path.join(os.path.dirname(__file__), 'suggestion.html')
130 self.response.out.write(template.render(template_file, template_values))
132 def post(self):
133 now = datetime.datetime.now()
134 when = whenfromcreated(now)
135 s = Suggestion(
136 suggestion = self.request.get('suggestion'),
137 when=when,
138 created=now)
139 s.put()
141 self.redirect('/unique/')
144 class SuggestionPopulate(webapp.RequestHandler):
145 def post(self):
146 now = datetime.datetime.now()
147 for i in range(6):
148 s = Suggestion(
149 suggestion = 'Suggestion %d' % i,
150 created = now,
151 when = whenfromcreated(now))
152 s.put()
154 self.redirect('/unique/')
157 def main():
158 application = webapp.WSGIApplication([
159 ('/unique/pop/', SuggestionPopulate),
160 ('/unique/', SuggestionHandler)
161 ], debug=True)
162 wsgiref.handlers.CGIHandler().run(application)
165 if __name__ == '__main__':
166 main()