def vote(up, id, vote_new): """ Vote up/down for a single word. AJAX action. Possible votes: 0 = vote down 1 = vote up 2 = don't know """ word = db.Word.get_or_404(id) vote_up = int(up) # 0, 1, or 2 directions = ('votes.down', 'votes.up') # Remember votes, do not allow double voting. # We cache: '<ip_addr>:<wordid> => [01]', e.g.: '127.0.0.1:43a...0001 => 1' ip = request.remote_addr vote = cache.get('%s:%s' % (ip, id)) if not vote or vote != up: to_update = {} # Pending DB updates. # Count a vote unless this is a "don't know". if up != '2': # If previously voted, update vote, do not recount. if up not in (vote, '2'): to_update[directions[int(not vote_up)]] = -1 # Cast vote now. to_update[directions[vote_up]] = 1 db.Word.collection.update({'_id': id}, {"$inc": to_update}) # ... and remember this. cache.set('%s:%s' % (ip, id), up, timeout=app.config['CACHE_VOTE_TIMEOUT']) # Index word if enough votes have been cast. If fewer, # remove from index word = db.Word.one({'_id': id}) if word.votes.up >= app.config['MIN_VOTES']: elastic.index_word(word=word) else: elastic.remove_word(word=word) if not request.is_xhr: flash(u'Danke für deine Stimme!', 'success') if vote_new: return redirect(url_for('vote_new')) else: return redirect(word.to_url) else: return 'ok'
def vote_new(): """Vote on new submissions.""" words = db.Word.find( {'$and': [{'votes.up': {'$lt': app.config['MIN_VOTES']}}, {'votes.down': {'$lt': app.config['MIN_VOTES']}}]}, sort=[('url.token', pymongo.ASCENDING)]) # Find a word that's not been voted on yet ip = request.remote_addr myword = None for word in words: if cache.get('%s:%s' % (ip, word._id)) is None: myword = word break return render_template('vote_new.html', word=myword)