def daily_breakdown(session, day_from=None, day_to=None): def _calc(): stats = {} if day_from is not None and day_to is not None: # fill in gaps for day in util.daterange(day_from,day_to): stats[day] = dict(total=0,done=0,help=0) # TODO: do the work in the database. q = session.query(cast(Article.pubdate,Date), Article) if day_from is not None: q = q.filter(cast(Article.pubdate, Date) >= day_from) if day_to is not None: q = q.filter(cast(Article.pubdate, Date) <= day_to) for day,art in q: if day not in stats: stats[day] = dict(total=0,done=0,help=0) stats[day]['total'] += 1 if not art.needs_sourcing: stats[day]['done'] += 1 stats = sorted([(day,row) for day,row in stats.iteritems()], key=lambda x: x[0], reverse=True ) return [DailyStats(x[0], x[1]['total'], x[1]['done']) for x in stats] k = "daily_breakdown_from_%s_to_%s" % (day_from, day_to) return cache.get_or_create(k, _calc, 60*1)
def calc_top_sourcers(session, ndays=7, cache_expiration_time=60*5): """ returns list of (user, src_cnt) tuples """ def _calc(): src_cnts = session.query(Source.creator_id, func.count('*').label('cnt')) if ndays is not None: day_to = datetime.datetime.utcnow() day_from = day_to - datetime.timedelta(days=ndays) src_cnts = src_cnts.\ filter(cast(Source.created, Date) >= day_from).\ filter(cast(Source.created, Date) <= day_to) src_cnts = src_cnts.\ group_by(Source.creator_id).\ subquery() top_sourcers = session.query(UserAccount, src_cnts.c.cnt).\ options(joinedload('photo')).\ join(src_cnts, UserAccount.id==src_cnts.c.creator_id).\ order_by(src_cnts.c.cnt.desc()).\ limit(6).\ all() return top_sourcers if ndays is None: cachename = 'top_sourcers_alltime' else: cachename = 'top_sourcers_%d_days' % (ndays) return cache.get_or_create(cachename, _calc, expiration_time=cache_expiration_time)
def thumbnail(self, filename, w, h): k = "%s_%s_%s" %(filename,w,h) def _calc(): original = Image.open(os.path.join(settings.uploads_path,filename)) thumb = original.convert() # convert() rather than copy() - copy leaves palette intact, which makes for crumby thumbs thumb.thumbnail((w,h), Image.ANTIALIAS) buf= StringIO.StringIO() thumb.save(buf, format='PNG') return 'image/png',buf.getvalue() return cache.get_or_create(k,_calc)
def thumbnail(self, filename, w, h): k = "%s_%s_%s" % (filename, w, h) def _calc(): original = Image.open(os.path.join(settings.uploads_path, filename)) thumb = original.convert( ) # convert() rather than copy() - copy leaves palette intact, which makes for crumby thumbs thumb.thumbnail((w, h), Image.ANTIALIAS) buf = StringIO.StringIO() thumb.save(buf, format='PNG') return 'image/png', buf.getvalue() return cache.get_or_create(k, _calc)
def get(self): top_sourcers_7days = calc_top_sourcers(self.session, ndays=7, cache_expiration_time=60*5) top_sourcers_alltime = calc_top_sourcers(self.session, ndays=None, cache_expiration_time=60*60*12) # daily breakdown for the week today = datetime.datetime.utcnow().date() stats = daily_breakdown(self.session, today-datetime.timedelta(days=6), today) max_arts = max(stats, key=lambda x: x.total).total def _get_recent_actions(): recent_actions = self.session.query(Action).\ options(joinedload('article'),joinedload('user'),joinedload('source'),joinedload('comment'),joinedload('label')).\ filter(Action.what.in_(('src_add','art_add','mark_sourced','mark_unsourced','helpreq_open','helpreq_close','label_add','label_remove'))).\ order_by(Action.performed.desc()).slice(0,6).all() return recent_actions recent_actions = cache.get_or_create("recent_actions", _get_recent_actions, 10) # 4 sample articles (3 unsourced, one sourced as an example) # TODO: should probably bias these toward being >1day old def _recent_arts_unsourced(): return self.session.query(Article).\ options(joinedload('sources'),joinedload('comments')).\ filter(Article.needs_sourcing==True).\ order_by(Article.pubdate.desc()).\ limit(50).\ all() def _recent_arts_sourced(): return self.session.query(Article).\ options(joinedload('sources'),joinedload('comments')).\ filter(Article.needs_sourcing==False).\ order_by(Article.pubdate.desc()).\ limit(50).\ all() sourced_arts = cache.get_or_create("recent_arts_sourced",_recent_arts_sourced, 60*17) unsourced_arts = cache.get_or_create("recent_arts_unsourced",_recent_arts_unsourced, 60*15) random_arts = [] if len(unsourced_arts)>0: random_arts += random.sample(unsourced_arts, 3) if len(sourced_arts)>0: random_arts += random.sample(sourced_arts, 1) random.shuffle(random_arts) # note: because of caching, a lot of the sqlalchemy objects will be # session-less (detached), so the template will fail if any further # database queries are triggered. # we could merge cached objects back into the session, but # that's silly - we should be avoiding fine-grained on-the-fly # additional queries anyway. self.render('front.html', random_arts = random_arts, recent_actions = recent_actions, groupby = itertools.groupby, top_sourcers_7days = top_sourcers_7days, top_sourcers_alltime = top_sourcers_alltime, week_stats=stats, week_stats_max_arts=max_arts)