def get_votes(instance): from .thread import Thread from .email import Email from .vote import Vote def _getvalue(): if isinstance(instance, Thread): filters = {"email__thread_id": instance.id} elif isinstance(instance, Email): filters = {"email_id": instance.id} else: ValueError("The 'get_votes' function only accepts 'Email' " "and 'Thread' instance") votes = list(Vote.objects.filter(**filters).values_list( "value", flat=True)) return ( len([v for v in votes if v == 1]), len([v for v in votes if v == -1]), ) cache_key = "%s:%s:votes" % (instance.__class__.__name__, instance.id) votes = cache.get_or_set(cache_key, _getvalue, None) likes, dislikes = votes # XXX: use an Enum? if likes - dislikes >= 10: status = "likealot" elif likes - dislikes > 0: status = "like" else: status = "neutral" return {"likes": likes, "dislikes": dislikes, "status": status}
def top_posters(self): def _get_posters(): from .email import Email # avoid circular imports begin_date, end_date = self.get_recent_dates() query = Email.objects.filter( mailinglist=self, date__gte=begin_date, date__lt=end_date, ).only("sender", "sender_name").select_related("sender") posters = {} for email in query: key = (email.sender.address, email.sender_name) if key not in posters: posters[key] = 1 else: posters[key] += 1 posters = [ {"address": p[0], "name": p[1], "count": c} for p, c in posters.items() ] sorted_posters = sorted( posters, key=lambda p: p["count"], reverse=True) return sorted_posters[:5] return cache.get_or_set( "MailingList:%s:top_posters" % self.name, _get_posters, 3600 * 6) # 6 hours
def get_participants_count_for_month(self, year, month): def _get_value(): begin_date = datetime.datetime(year, month, 1, tzinfo=utc) end_date = begin_date + datetime.timedelta(days=32) end_date = end_date.replace(day=1) return self.get_participants_count_between(begin_date, end_date) return cache.get_or_set( "MailingList:%s:p_count_for:%s:%s" % (self.name, year, month), _get_value, None)
def top_posters(self): begin_date, end_date = self.get_recent_dates() query = Sender.objects.filter( emails__mailinglist=self, emails__date__gte=begin_date, emails__date__lt=end_date, ).annotate(count=models.Count("emails")).order_by("-count") # Because of South, ResultSets are not pickleizable directly, they must # be converted to lists (there's an extra field without the _deferred # attribute that causes tracebacks) return cache.get_or_set("MailingList:%s:top_posters" % self.name, lambda: list(query[:5]), 3600 * 6) # 6 hours
def get_subscriptions(user): # Get subscriptions for the provided Django user. def _get_value(): mm_user = get_mailman_user(user) if mm_user is None: return {} subscriptions = dict([(member.list_id, member.address) for member in mm_user.subscriptions]) return subscriptions # TODO: how should this be invalidated? Subscribe to a signal in # mailman when a new subscription occurs? Or store in the session? return cache.get_or_set("User:%s:subscriptions" % user.id, _get_value, 60, version=2) # 1 minute
def get_months(mlist): """ Return a dictionnary of years, months for which there are potentially archives available for a given list (based on the oldest post on the list). :arg list_name, name of the mailing list in which this email should be searched. """ date_first = cache.get_or_set( "MailingList:%s:first_date" % mlist.name, lambda: mlist.emails. order_by("date").values_list("date", flat=True).first(), None) now = datetime.datetime.now() if not date_first: # No messages on this list, return the current month. return {now.year: [now.month]} archives = {} year = date_first.year month = date_first.month while year < now.year: archives[year] = range(1, 13)[(month - 1):] year = year + 1 month = 1 archives[now.year] = range(1, 13)[:now.month] return archives
def subject(self): return cache.get_or_set( "Thread:%s:subject" % self.id, lambda: self.starting_email.subject, None)
def emails_count(self): return cache.get_or_set( "Thread:%s:emails_count" % self.id, lambda: self.emails.count(), None)
def participants_count(self): return cache.get_or_set( "Thread:%s:participants_count" % self.id, lambda: self.participants.count(), None)
def recent_participants_count(self): begin_date, end_date = self.get_recent_dates() return cache.get_or_set( "MailingList:%s:recent_participants_count" % self.name, lambda: self.get_participants_count_between(begin_date, end_date), 3600 * 6) # 6 hours