Commits

Ryan Witt committed 3f636cd

Added a utility function to get a users's badge counts in one db query. This speeds up my badge detail page rendering by over 6x.

Comments (0)

Files changed (2)

badges/templatetags/badges_tags.py

 from django.template import Library
+from badges.utils import badge_count
+from badges.models import LEVEL_CHOICES
+level_choices = dict(LEVEL_CHOICES)
 
 register = Library()
 
 def level_count(badges, level):
    return badges.filter(level=level).count()
 
+@register.filter
+def level_title(level):
+   return level_choices[level]
 
+@register.filter('badge_count')
+def _badge_count(user_or_qs):
+   return badge_count(user_or_qs)
 
-
-
-
-
-
-
 from badges.models import Badge as BadgeModel
 from badges.models import BadgeToUser
 
+from django.contrib.auth.models import User
 
 registered_badges = {}
 
         registered_badges[badge.id] = badge()
     return badge
 
+def badge_count(user_or_qs):
+    """
+    Given a user or queryset of users, this returns the badge
+    count at each badge level that the user(s) have earned.
+
+    Example:
+
+     >>> badge_count(User.objects.filter(username='admin'))
+     [{'count': 20, 'badge__level': u'1'}, {'count': 1, 'badge__level': u'2'}, {'count': 1, 'badge__level': u'3'}]
+
+    Uses a single database query.
+    """
+    if isinstance(user_or_qs, User):
+        kwargs = dict(user=user_or_qs)
+    else:
+        kwargs = dict(user__in=user_or_qs)
+
+    return BadgeToUser.objects.filter(
+        **kwargs
+    ).values(
+        'badge__level',
+    ).annotate(
+        count=models.Count('badge__level'),
+    ).order_by('badge__level')
 
 class MetaBadgeMeta(type):