def get(self, username): """ Render a user page. """ publicuser = UserPrefs.all().filter('name =', username).get() if not publicuser: self.abort(404) recipes = Recipe.all()\ .filter('owner =', publicuser)\ .order('name')\ .run(limit=25) actions = UserAction.all()\ .filter('owner =', publicuser)\ .order('-created')\ .fetch(15) object_ids = UserAction.gather_object_ids(actions) user_map = {publicuser.key().id(): publicuser} for user in UserPrefs.get_by_id(object_ids['users']): user_map[user.key().id()] = user recipes = [r for r in recipes] recipe_ids = [recipe.key().id() for recipe in recipes] object_ids['recipes'] = [ id for id in object_ids['recipes'] if id not in recipe_ids ] recipe_map = {} for recipe in recipes: recipe.owner = publicuser recipe_map[recipe.key().id()] = recipe for recipe in Recipe.get_by_id(object_ids['recipes']): recipe_map[recipe.key().id()] = recipe brew_map = {} for brew in Brew.get_by_id(object_ids['brews']): brew_map[brew.key().id()] = brew self.render( 'user.html', { 'publicuser': publicuser, 'recipes': recipes, 'actions': actions, 'user_map': user_map, 'recipe_map': recipe_map, 'brew_map': brew_map })
def get(self, username): """ Render a user page. """ publicuser = UserPrefs.all().filter('name =', username).get() if not publicuser: self.abort(404) recipes = Recipe.all()\ .filter('owner =', publicuser)\ .order('name')\ .run(limit=25) actions = UserAction.all()\ .filter('owner =', publicuser)\ .order('-created')\ .fetch(15) object_ids = UserAction.gather_object_ids(actions) user_map = { publicuser.key().id(): publicuser } for user in UserPrefs.get_by_id(object_ids['users']): user_map[user.key().id()] = user recipes = [r for r in recipes] recipe_ids = [recipe.key().id() for recipe in recipes] object_ids['recipes'] = [id for id in object_ids['recipes'] if id not in recipe_ids] recipe_map = {} for recipe in recipes: recipe.owner = publicuser recipe_map[recipe.key().id()] = recipe for recipe in Recipe.get_by_id(object_ids['recipes']): recipe_map[recipe.key().id()] = recipe brew_map = {} for brew in Brew.get_by_id(object_ids['brews']): brew_map[brew.key().id()] = brew self.render('user.html', { 'publicuser': publicuser, 'recipes': recipes, 'actions': actions, 'user_map': user_map, 'recipe_map': recipe_map, 'brew_map': brew_map })
def process(self, username, action): """ Follow the given user. """ user = UserPrefs.get() publicuser = UserPrefs.all().filter('name =', username).get() if not user or not publicuser: return self.render_json({ 'status': 'error', 'error': 'User not found' }) if action == 'post': if publicuser.user_id in user.following: return self.render_json({ 'status': 'error', 'error': 'Already following user' }) user.following.append(publicuser.user_id) existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_USER_FOLLOWED)\ .filter('object_id =', publicuser.key().id())\ .count() if not existing: user_action = UserAction() user_action.owner = user user_action.type = user_action.TYPE_USER_FOLLOWED user_action.object_id = publicuser.key().id() user_action.put() else: if publicuser.user_id not in user.following: return self.render_json({ 'status': 'error', 'error': 'User not being followed' }) user.following.remove(publicuser.user_id) existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_USER_FOLLOWED)\ .filter('object_id =', publicuser.key().id())\ .get() if existing: existing.delete() # Save updated following list user.put() self.render_json({ 'status': 'ok' })
def process(self, action, username=None, recipe_slug=None): """ Process a request to add or remove a user from the liked list. """ user = UserPrefs.get() publicuser = UserPrefs.all()\ .filter('name = ', username)\ .get() if not publicuser: self.render_json({'status': 'error', 'error': 'User not found'}) return recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug =', recipe_slug)\ .get() if not recipe: self.render_json({'status': 'error', 'error': 'Recipe not found'}) return if action == 'post': if user.user_id not in recipe.likes: recipe.likes.append(user.user_id) recipe.put() existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_RECIPE_LIKED)\ .filter('object_id =', recipe.key().id())\ .count() if not existing: user_action = UserAction() user_action.owner = user user_action.type = user_action.TYPE_RECIPE_LIKED user_action.object_id = recipe.key().id() user_action.put() elif action == 'delete': if user.user_id in recipe.likes: recipe.likes.remove(user.user_id) recipe.put() existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_RECIPE_LIKED)\ .filter('object_id =', recipe.key().id())\ .get() if existing: existing.delete() return self.render_json({'status': 'ok', 'likes': len(recipe.likes)})
def process(self, username, action): """ Follow the given user. """ user = self.user publicuser = UserPrefs.all().filter('name =', username).get() if not user or not publicuser: return self.render_json({ 'status': 'error', 'error': 'User not found' }) if action == 'post': if publicuser.user_id in user.following: return self.render_json({ 'status': 'error', 'error': 'Already following user' }) user.following.append(publicuser.user_id) existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_USER_FOLLOWED)\ .filter('object_id =', publicuser.key().id())\ .count() if not existing: user_action = UserAction() user_action.owner = user user_action.type = user_action.TYPE_USER_FOLLOWED user_action.object_id = publicuser.key().id() user_action.put() else: if publicuser.user_id not in user.following: return self.render_json({ 'status': 'error', 'error': 'User not being followed' }) user.following.remove(publicuser.user_id) existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_USER_FOLLOWED)\ .filter('object_id =', publicuser.key().id())\ .get() if existing: existing.delete() # Save updated following list user.put() self.render_json({ 'status': 'ok' })
def post(self): """ Process a donation payment given a Stripe single-use token. """ user = self.user stripe.api_key = settings.STRIPE_PRIVATE_KEY amount = int(cgi.escape(self.request.get('amount'))) token = cgi.escape(self.request.get('stripeToken')) # Charge the amount (in cents) to the customer's card charge = stripe.Charge.create(**{ 'amount': amount * 100, 'currency': 'usd', 'card': token, 'description': 'Donation from ' + (user and user.name or 'Anonymous') }) if user: # Add an award to this user for donating if user and 'donated' not in user.awards: user.awards.append('donated') user.put() # Log action action = UserAction() action.owner = user action.type = action.TYPE_USER_DONATED action.put() self.redirect('/donate?success=true')
def top_interesting_events(self): """ Get a list of interesting events ordered by date from most recent to least. Interesting events are events that either belong to this user or any user she is following. """ from models.useraction import UserAction following = self.following_users.run(batch_size=100) return UserAction.all()\ .filter('owner IN', [self] + list(following))\ .order('-created')\ .fetch(25)
def post(self, username=None, recipe_slug=None): publicuser = UserPrefs.all()\ .filter('name = ', username)\ .get() if not publicuser: self.render_json({ 'status': 'error', 'error': 'User not found' }) return recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug =', recipe_slug)\ .get() if not recipe: self.render_json({ 'status': 'error', 'error': 'Recipe not found' }) return new_recipe = Recipe(**{ 'owner': UserPrefs.get(), 'cloned_from': recipe, 'color': recipe.color, 'ibu': recipe.ibu, 'alcohol': recipe.alcohol, 'name': recipe.name, 'description': recipe.description, 'type': recipe.type, 'style': recipe.style, 'batch_size': recipe.batch_size, 'boil_size': recipe.boil_size, 'bottling_temp': recipe.bottling_temp, 'bottling_pressure': recipe.bottling_pressure, '_ingredients': recipe._ingredients }) new_recipe.slug = generate_usable_slug(new_recipe) new_recipe.put() action = UserAction() action.owner = UserPrefs.get() action.type = action.TYPE_RECIPE_CLONED action.object_id = new_recipe.key().id() action.put() return self.render_json({ 'status': 'ok', 'redirect': new_recipe.url })
def delete(self, username=None, recipe_slug=None): """ Handle recipe delete. This will remove a recipe and return success or failure. """ user = self.user if not user: self.render_json({ 'status': 'error', 'error': 'User not logged in' }) recipe = Recipe.all()\ .filter('slug = ', recipe_slug)\ .filter('owner =', user)\ .get() if recipe: # Delete all actions pointing to this recipe actions = UserAction.all()\ .filter('type IN', [UserAction.TYPE_RECIPE_CREATED, UserAction.TYPE_RECIPE_EDITED, UserAction.TYPE_RECIPE_CLONED, UserAction.TYPE_RECIPE_LIKED])\ .filter('object_id =', recipe.key().id())\ .fetch(1000) for action in actions: action.delete() # Delete the actual recipe itself recipe.delete() self.render_json({ 'status': 'ok', 'redirect': '/users/%(username)s/recipes' % { 'username': user.name } }) else: self.render_json({ 'status': 'error', 'error': 'Unable to delete recipe' })
def post(self, username=None, recipe_slug=None): publicuser = UserPrefs.all()\ .filter('name = ', username)\ .get() if not publicuser: self.render_json({'status': 'error', 'error': 'User not found'}) return recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug =', recipe_slug)\ .get() if not recipe: self.render_json({'status': 'error', 'error': 'Recipe not found'}) return new_recipe = Recipe( **{ 'owner': UserPrefs.get(), 'cloned_from': recipe, 'color': recipe.color, 'ibu': recipe.ibu, 'alcohol': recipe.alcohol, 'name': recipe.name, 'description': recipe.description, 'type': recipe.type, 'style': recipe.style, 'batch_size': recipe.batch_size, 'boil_size': recipe.boil_size, 'bottling_temp': recipe.bottling_temp, 'bottling_pressure': recipe.bottling_pressure, '_ingredients': recipe._ingredients }) new_recipe.slug = generate_usable_slug(new_recipe) new_recipe.put() action = UserAction() action.owner = UserPrefs.get() action.type = action.TYPE_RECIPE_CLONED action.object_id = new_recipe.key().id() action.put() return self.render_json({'status': 'ok', 'redirect': new_recipe.url})
def post(self): """ Import a new recipe or list of recipes from BeerXML to the currently logged in user's account. """ user = self.user recipesxml = self.request.POST['file'].value for recipe in Recipe.new_from_beerxml(recipesxml): recipe.owner = user recipe.slug = generate_usable_slug(recipe) recipe.update_cache() key = recipe.put() action = UserAction() action.owner = user action.object_id = key.id() action.type = action.TYPE_RECIPE_CREATED action.put() self.redirect('/users/' + user.name + '/recipes')
def post(self): """ Import a new recipe or list of recipes from BeerXML to the currently logged in user's account. """ user = self.user recipesxml = self.request.POST['file'].value for recipe in Recipe.new_from_beerxml(recipesxml): recipe.owner = user recipe.slug = generate_usable_slug(recipe) recipe.update_cache(); key = recipe.put() action = UserAction() action.owner = user action.object_id = key.id() action.type = action.TYPE_RECIPE_CREATED action.put() self.redirect('/users/' + user.name + '/recipes')
def create_or_update(auth_id, user_info, auth_info): """ Create a new user or update an existing one with information such as id, name, email, avatar, etc. """ prefs = UserPrefs.all()\ .filter('user_id =', auth_id)\ .get() # Backwards compatibility if not prefs: prefs = UserPrefs.all()\ .filter('email =', user_info['email'])\ .get() if prefs: if ':' not in prefs.user_id: # Old-style user and the emails match, so update! prefs.user_id = auth_id else: # New-style user, ignore prefs = None # Not found yet... time to create a new one! if not prefs: # Generate a nice username from the email username = user_info['email'].split('@')[0].lower().replace(' ', '') count = 0 while True: check_name = count and username + str(count) or username if not UserPrefs.all()\ .filter('name =', check_name)\ .count() and check_name not in settings.RESERVED_USERNAMES: if count: username = username + str(count) break count += 1 # Create the preferences object and store it prefs = UserPrefs(**{ 'user_id': auth_id, 'name': username, 'joined': Date().date, }) # Write to the db so this user object gets a proper id, which # is required to reference it in the action created below prefs.put() from models.useraction import UserAction action = UserAction() action.owner = prefs action.type = action.TYPE_USER_JOINED action.put() # Invalidate cached user list pages memcache.delete('users-content') # Update fields based on latest user info prefs.email = user_info['email'] # Update the avatar, except for special users if prefs.name not in ['examples']: prefs.avatar = user_info['avatar'] prefs.put() return prefs
def get(self): """ Render the index page. Currently this renders a 'Coming soon' landing page that will eventually be replaced with a proper home page. """ user = self.user if user: # Try to get rendered output from memcache rendered = memcache.get('dashboard-' + user.user_id) if rendered and not settings.DEBUG: return self.response.out.write(rendered) # Fetch following users following = user.following_users\ .order('name')\ .fetch(100) user_keys = [user.key()] + [u.key() for u in following] # Start async fetch of top recipes top_recipes = Recipe.all()\ .filter('owner IN', user_keys)\ .order('-likes_count')\ .run(limit=15) # Get and process interesting events interesting_events = UserAction.all()\ .filter('owner IN', user_keys)\ .order('-created')\ .fetch(15) object_ids = UserAction.gather_object_ids(interesting_events) object_ids['users'] = [id for id in object_ids['users'] if id not in [user.key().id()] + user.following] # Start async fetch of relevant recipes recipes = db.get_async([Key.from_path('Recipe', id) for id in object_ids['recipes']]) # Convert iterators to lists of items in memory and setup a map # of user id -> user for easy lookups following = list(following) top_recipes = list(top_recipes) user_map = { user.key().id(): user } for u in following: user_map[u.key().id()] = u if object_ids['users']: for u in UserPrefs.get_by_id(object_ids['users']): user_map[u.key().id()] = u # Setup a map of recipe id -> recipe for easy lookups recipe_map = {} for r in recipes.get_result(): recipe_map[r.key().id()] = r # Render and cache for 1 minute memcache.set('dashboard-' + user.user_id, self.render('dashboard.html', { 'following': following, 'user_map': user_map, 'recipe_map': recipe_map, 'top_recipes': top_recipes, 'interesting_events': interesting_events }), 60) else: # Try to get rendered output from memcache rendered = memcache.get('index') if rendered and not settings.DEBUG: return self.response.out.write(rendered) recipes = Recipe.all()\ .order('-likes_count')\ .run(limit=15) # Render and cache for 15 minutes memcache.set('index', self.render('index.html', { 'recipes': recipes }), 900)
def post(self, username=None, recipe_slug=None): publicuser = UserPrefs.all()\ .filter('name = ', username)\ .get() if not publicuser: self.render_json({ 'status': 'error', 'error': 'User not found' }) return recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug =', recipe_slug)\ .get() if not recipe: self.render_json({ 'status': 'error', 'error': 'Recipe not found' }) return new_recipe = Recipe(**{ 'owner': self.user, 'cloned_from': recipe, 'color': recipe.color, 'ibu': recipe.ibu, 'alcohol': recipe.alcohol, 'name': recipe.name, 'description': recipe.description, 'type': recipe.type, 'category': recipe.category, 'style': recipe.style, 'batch_size': recipe.batch_size, 'boil_size': recipe.boil_size, 'bottling_temp': recipe.bottling_temp, 'bottling_pressure': recipe.bottling_pressure, 'steep_efficiency': recipe.steep_efficiency, 'mash_efficiency': recipe.mash_efficiency, 'primary_days': recipe.primary_days, 'primary_temp': recipe.primary_temp, 'secondary_days': recipe.secondary_days, 'secondary_temp': recipe.secondary_temp, 'tertiary_days': recipe.tertiary_days, 'tertiary_temp': recipe.tertiary_temp, 'aging_days': recipe.aging_days, '_ingredients': recipe._ingredients }) new_recipe.slug = generate_usable_slug(new_recipe) new_recipe.put() new_recipe.update_grade() new_recipe.put() # Update recipe ranking for sorting recipe.update_grade() recipe.put() action = UserAction() action.owner = self.user action.type = action.TYPE_RECIPE_CLONED action.object_id = new_recipe.key().id() action.put() return self.render_json({ 'status': 'ok', 'redirect': new_recipe.url })
def process(self, action, username=None, recipe_slug=None): """ Process a request to add or remove a user from the liked list. """ user = UserPrefs.get() publicuser = UserPrefs.all()\ .filter('name = ', username)\ .get() if not publicuser: self.render_json({ 'status': 'error', 'error': 'User not found' }) return recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug =', recipe_slug)\ .get() if not recipe: self.render_json({ 'status': 'error', 'error': 'Recipe not found' }) return if action == 'post': if user.user_id not in recipe.likes: recipe.likes.append(user.user_id) recipe.put() existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_RECIPE_LIKED)\ .filter('object_id =', recipe.key().id())\ .count() if not existing: user_action = UserAction() user_action.owner = user user_action.type = user_action.TYPE_RECIPE_LIKED user_action.object_id = recipe.key().id() user_action.put() elif action == 'delete': if user.user_id in recipe.likes: recipe.likes.remove(user.user_id) recipe.put() existing = UserAction.all()\ .filter('owner =', user)\ .filter('type =', UserAction.TYPE_RECIPE_LIKED)\ .filter('object_id =', recipe.key().id())\ .get() if existing: existing.delete() return self.render_json({ 'status': 'ok', 'likes': len(recipe.likes) })
def get(self): user = self.user # Try to get rendered output from memcache rendered = memcache.get('dashboard-' + user.user_id) if rendered and not settings.DEBUG: return self.response.out.write(rendered) # Fetch following users following = user.following_users\ .order('name')\ .fetch(100) user_keys = [user.key()] + [u.key() for u in following] # Start async fetch of top recipes top_recipes = Recipe.all()\ .filter('owner IN', user_keys)\ .order('-grade')\ .run(limit=15) # Get and process interesting events interesting_events = UserAction.all()\ .filter('owner IN', user_keys)\ .order('-created')\ .fetch(15) object_ids = UserAction.gather_object_ids(interesting_events) object_ids['users'] = [ id for id in object_ids['users'] if id not in [user.key().id()] + user.following ] # Start async fetch of relevant recipes recipes = db.get_async( [Key.from_path('Recipe', id) for id in object_ids['recipes']]) # Start async fetch of relevant brews brews = db.get_async( [Key.from_path('Brew', id) for id in object_ids['brews']]) # Convert iterators to lists of items in memory and setup a map # of user id -> user for easy lookups following = list(following) top_recipes = list(top_recipes) user_map = {user.key().id(): user} for u in following: user_map[u.key().id()] = u if object_ids['users']: for u in UserPrefs.get_by_id(object_ids['users']): user_map[u.key().id()] = u # Setup a map of brew id -> brew for easy lookups brew_map = {} brew_recipe_ids = set() for b in brews.get_result(): brew_recipe_ids.add(b.recipe_key.id()) brew_map[b.key().id()] = b # Async fetch of any recipes brews reference that weren't # included in the recipe fetch above... brew_recipes = db.get_async([ Key.from_path('Recipe', id) for id in brew_recipe_ids if id not in object_ids['recipes'] ]) # Setup a map of recipe id -> recipe for easy lookups recipe_map = {} for r in recipes.get_result(): recipe_map[r.key().id()] = r for r in brew_recipes.get_result(): recipe_map[r.key().id()] = r # Render and cache for 1 minute memcache.set( 'dashboard-' + user.user_id, self.render( 'dashboard.html', { 'following': following, 'user_map': user_map, 'recipe_map': recipe_map, 'brew_map': brew_map, 'top_recipes': top_recipes, 'interesting_events': interesting_events }), self.CACHE_TIME)
key = recipe.put() # Save the historic version to database historic.put() changed = True else: # Save recipe to database key = recipe.put() # Update grade now that we have a key recipe.update_grade() recipe.put() if not historic or changed: action = UserAction() action.owner = user action.object_id = key.id() if not recipe_slug: action.type = action.TYPE_RECIPE_CREATED else: action.type = action.TYPE_RECIPE_EDITED action.put() self.render_json({ 'status': 'ok', 'redirect': '/users/%(username)s/recipes/%(slug)s' % { 'username': user.name, 'slug': recipe.slug
def get(self): """ Render the index page. Currently this renders a 'Coming soon' landing page that will eventually be replaced with a proper home page. """ user = self.user if user: # Try to get rendered output from memcache rendered = memcache.get('dashboard-' + user.user_id) if rendered and not settings.DEBUG: return self.response.out.write(rendered) # Fetch following users following = user.following_users\ .order('name')\ .fetch(100) user_keys = [user.key()] + [u.key() for u in following] # Start async fetch of top recipes top_recipes = Recipe.all()\ .filter('owner IN', user_keys)\ .order('-likes_count')\ .run(limit=15) # Get and process interesting events interesting_events = UserAction.all()\ .filter('owner IN', user_keys)\ .order('-created')\ .fetch(15) object_ids = UserAction.gather_object_ids(interesting_events) object_ids['users'] = [ id for id in object_ids['users'] if id not in [user.key().id()] + user.following ] # Start async fetch of relevant recipes recipes = db.get_async( [Key.from_path('Recipe', id) for id in object_ids['recipes']]) # Convert iterators to lists of items in memory and setup a map # of user id -> user for easy lookups following = list(following) top_recipes = list(top_recipes) user_map = {user.key().id(): user} for u in following: user_map[u.key().id()] = u if object_ids['users']: for u in UserPrefs.get_by_id(object_ids['users']): user_map[u.key().id()] = u # Setup a map of recipe id -> recipe for easy lookups recipe_map = {} for r in recipes.get_result(): recipe_map[r.key().id()] = r # Render and cache for 1 minute memcache.set( 'dashboard-' + user.user_id, self.render( 'dashboard.html', { 'following': following, 'user_map': user_map, 'recipe_map': recipe_map, 'top_recipes': top_recipes, 'interesting_events': interesting_events }), 60) else: # Try to get rendered output from memcache rendered = memcache.get('index') if rendered and not settings.DEBUG: return self.response.out.write(rendered) recipes = Recipe.all()\ .order('-likes_count')\ .run(limit=15) # Render and cache for 15 minutes memcache.set('index', self.render('index.html', {'recipes': recipes}), 900)
def get(self): user = self.user # Try to get rendered output from memcache rendered = memcache.get('dashboard-' + user.user_id) if rendered and not settings.DEBUG: return self.response.out.write(rendered) # Fetch following users following = user.following_users\ .order('name')\ .fetch(100) user_keys = [user.key()] + [u.key() for u in following] # Start async fetch of top recipes top_recipes = Recipe.all()\ .filter('owner IN', user_keys)\ .order('-grade')\ .run(limit=15) # Get and process interesting events interesting_events = UserAction.all()\ .filter('owner IN', user_keys)\ .order('-created')\ .fetch(15) object_ids = UserAction.gather_object_ids(interesting_events) object_ids['users'] = [id for id in object_ids['users'] if id not in [user.key().id()] + user.following] # Start async fetch of relevant recipes recipes = db.get_async([Key.from_path('Recipe', id) for id in object_ids['recipes']]) # Start async fetch of relevant brews brews = db.get_async([Key.from_path('Brew', id) for id in object_ids['brews']]) # Convert iterators to lists of items in memory and setup a map # of user id -> user for easy lookups following = list(following) top_recipes = list(top_recipes) user_map = { user.key().id(): user } for u in following: user_map[u.key().id()] = u if object_ids['users']: for u in UserPrefs.get_by_id(object_ids['users']): user_map[u.key().id()] = u # Setup a map of brew id -> brew for easy lookups brew_map = {} brew_recipe_ids = set() for b in brews.get_result(): brew_recipe_ids.add(b.recipe_key.id()) brew_map[b.key().id()] = b # Async fetch of any recipes brews reference that weren't # included in the recipe fetch above... brew_recipes = db.get_async([Key.from_path('Recipe', id) for id in brew_recipe_ids if id not in object_ids['recipes']]) # Setup a map of recipe id -> recipe for easy lookups recipe_map = {} for r in recipes.get_result(): recipe_map[r.key().id()] = r for r in brew_recipes.get_result(): recipe_map[r.key().id()] = r # Render and cache for 1 minute memcache.set('dashboard-' + user.user_id, self.render('dashboard.html', { 'following': following, 'user_map': user_map, 'recipe_map': recipe_map, 'brew_map': brew_map, 'top_recipes': top_recipes, 'interesting_events': interesting_events }), self.CACHE_TIME)
class BrewHandler(BaseHandler): """ Create a new brew. /users/USERNAME/recipes/RECIPE-SLUG/brew /users/USERNAME/recipes/RECIPE-SLUG/brew/BREW-SLUG """ def process(self, username=None, recipe_slug=None, brew_slug=None): publicuser = UserPrefs.all()\ .filter('name =', username)\ .get() if not publicuser: return [None, None, None] recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug = ', recipe_slug)\ .get() if not recipe: return [publicuser, None, None] if brew_slug is not None: brew = Brew.all()\ .filter('owner =', publicuser)\ .filter('recipe =', recipe)\ .filter('slug =', brew_slug)\ .get() if not brew: return [publicuser, recipe, None] else: brew = Brew() brew.owner = self.user brew.recipe = recipe return [publicuser, recipe, brew] def get(self, username=None, recipe_slug=None, brew_slug=None): publicuser, recipe, brew = self.process(username, recipe_slug, brew_slug) if not publicuser or not recipe or not brew: return self.abort(404) self.render('brew.html', { 'publicuser': publicuser, 'recipe': recipe, 'brew': brew }) def post(self, username=None, recipe_slug=None, brew_slug=None): publicuser, recipe, brew = self.process(username, recipe_slug, brew_slug) if not publicuser or not recipe or not brew: return self.abort(404) # Does the current user own this? If not, then fail if brew.owner.name != self.user.name: return self.abort(403) submitted = json.loads(cgi.escape(self.request.get('brew'))) logging.info(submitted) started = submitted['started'] bottled = submitted['bottled'] for k, v in [('started', started), ('bottled', bottled)]: if v.strip(): try: d = Date(v, format="%H:%M %d %b %Y") except Exception, e: return self.render_json({ 'status': 'error', 'error': 'Could not process date "%s": %s' % (v, e) }) setattr(brew, k, d.datetime) brew.og = float(submitted['og']) brew.fg = float(submitted['fg']) brew.rating = submitted['rating'] brew.notes = submitted['notes'] brew.slug = generate_usable_slug(brew) key = brew.put() # Update recipe ranking information for sorting recipe.update_grade() recipe.put() # Add user action action = UserAction() action.owner = self.user action.object_id = key.id() if not brew_slug: action.type = action.TYPE_BREW_CREATED else: action.type = action.TYPE_BREW_UPDATED action.put() self.render_json({'status': 'ok'})
def post(self, username=None, recipe_slug=None): publicuser = UserPrefs.all()\ .filter('name = ', username)\ .get() if not publicuser: self.render_json({'status': 'error', 'error': 'User not found'}) return recipe = Recipe.all()\ .filter('owner =', publicuser)\ .filter('slug =', recipe_slug)\ .get() if not recipe: self.render_json({'status': 'error', 'error': 'Recipe not found'}) return new_recipe = Recipe( **{ 'owner': self.user, 'cloned_from': recipe, 'color': recipe.color, 'ibu': recipe.ibu, 'alcohol': recipe.alcohol, 'name': recipe.name, 'description': recipe.description, 'type': recipe.type, 'category': recipe.category, 'style': recipe.style, 'batch_size': recipe.batch_size, 'boil_size': recipe.boil_size, 'bottling_temp': recipe.bottling_temp, 'bottling_pressure': recipe.bottling_pressure, 'steep_efficiency': recipe.steep_efficiency, 'mash_efficiency': recipe.mash_efficiency, 'primary_days': recipe.primary_days, 'primary_temp': recipe.primary_temp, 'secondary_days': recipe.secondary_days, 'secondary_temp': recipe.secondary_temp, 'tertiary_days': recipe.tertiary_days, 'tertiary_temp': recipe.tertiary_temp, 'aging_days': recipe.aging_days, '_ingredients': recipe._ingredients }) new_recipe.slug = generate_usable_slug(new_recipe) new_recipe.put() new_recipe.update_grade() new_recipe.put() # Update recipe ranking for sorting recipe.update_grade() recipe.put() action = UserAction() action.owner = self.user action.type = action.TYPE_RECIPE_CLONED action.object_id = new_recipe.key().id() action.put() return self.render_json({'status': 'ok', 'redirect': new_recipe.url})