Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added get_scores_in_bulk helper method and scores_for_objects templat…

…e tag

git-svn-id: https://django-voting.googlecode.com/svn/trunk@35 662f01ad-f42a-0410-a340-718c64ddaef4
  • Loading branch information...
commit 6e2e9aabdd3b3f7bce26062e8e1cd0942f2d8415 1 parent b41c19b
Jonathan Buchanan insin authored

Showing 3 changed files with 71 additions and 1 deletion. Show diff stats Hide diff stats

  1. +17 0 README.txt
  2. +24 1 models.py
  3. +30 0 templatetags/voting_tags.py
17 README.txt
@@ -79,6 +79,12 @@ functions:
79 79
80 80 Returns a dictionary with ``score`` and ``num_votes`` keys.
81 81
  82 + * ``get_scores_in_bulk(objects)`` -- Gets score and vote count
  83 + details for all the given objects. Score details consist of a
  84 + dictionary which has ``score`` and ``num_vote`` keys.
  85 +
  86 + Returns a dictionary mapping object ids to score details.
  87 +
82 88 * ``get_top(Model, limit=10, reversed=False)`` -- Gets the top
83 89 ``limit`` scored objects for a given model.
84 90
@@ -312,6 +318,17 @@ Example usage::
312 318 {{ score.score }} point{{ score.score|pluralize }}
313 319 after {{ score.num_votes }} vote{{ score.num_votes|pluralize }}
314 320
  321 +scores_for_objects
  322 +~~~~~~~~~~~~~~~~~~
  323 +
  324 +Retrieves the total scores and number of votes cast for a list of
  325 +objects as a dictionary keyed with the objects' ids and stores it in a
  326 +context variable.
  327 +
  328 +Example usage::
  329 +
  330 + {% scores_for_objects widget_list as scores %}
  331 +
315 332 vote_by_user
316 333 ~~~~~~~~~~~~
317 334
25 models.py
... ... @@ -1,4 +1,4 @@
1   -from django.db import models, connection
  1 +from django.db import backend, connection, models
2 2 from django.contrib.contenttypes.models import ContentType
3 3 from django.contrib.auth.models import User
4 4
@@ -17,6 +17,29 @@ def get_score(self, obj):
17 17 result = cursor.fetchall()[0]
18 18 return {'score': result[0] or 0, 'num_votes': result[1]}
19 19
  20 + def get_scores_in_bulk(self, objects):
  21 + """
  22 + Get a dictionary mapping object ids to total score and number
  23 + of votes for each object.
  24 + """
  25 + query = """
  26 +SELECT object_id, SUM(vote), COUNT(vote)
  27 +FROM %s
  28 +WHERE content_type_id = %%s
  29 + AND object_id IN (%s)
  30 +GROUP BY object_id""" % (
  31 + backend.quote_name(self.model._meta.db_table),
  32 + ','.join(['%s'] * len(objects))
  33 + )
  34 + ctype = ContentType.objects.get_for_model(objects[0])
  35 + cursor = connection.cursor()
  36 + cursor.execute(query, [ctype.id] + [obj.id for obj in objects])
  37 + results = cursor.fetchall()
  38 + return dict([(object_id, {
  39 + 'score': score,
  40 + 'num_votes': num_votes,
  41 + }) for object_id, score, num_votes in results])
  42 +
20 43 def record_vote(self, obj, user, vote):
21 44 """
22 45 Record a user's vote on a given object. Only allows a given user
30 templatetags/voting_tags.py
@@ -20,6 +20,19 @@ def render(self, context):
20 20 context[self.context_var] = Vote.objects.get_score(self.object)
21 21 return ''
22 22
  23 +class ScoresForObjectsNode(template.Node):
  24 + def __init__(self, objects, context_var):
  25 + self.objects = objects
  26 + self.context_var = context_var
  27 +
  28 + def render(self, context):
  29 + try:
  30 + objects = template.resolve_variable(self.objects, context)
  31 + except template.VariableDoesNotExist:
  32 + return ''
  33 + context[self.context_var] = Vote.objects.get_scores_in_bulk(objects)
  34 + return ''
  35 +
23 36 class VoteByUserNode(template.Node):
24 37 def __init__(self, user, object, context_var):
25 38 self.user = user
@@ -85,6 +98,22 @@ def do_score_for_object(parser, token):
85 98 raise template.TemplateSyntaxError("second argument to '%s' tag must be 'as'" % bits[0])
86 99 return ScoreForObjectNode(bits[1], bits[3])
87 100
  101 +def do_scores_for_objects(parser, token):
  102 + """
  103 + Retrieves the total scores for a list of objects and the number of
  104 + votes they have received and stores them in a context variable.
  105 +
  106 + Example usage::
  107 +
  108 + {% scores_for_objects widget_list as score_dict %}
  109 + """
  110 + bits = token.contents.split()
  111 + if len(bits) != 4:
  112 + raise template.TemplateSyntaxError("'%s' tag takes exactly three arguments" % bits[0])
  113 + if bits[2] != 'as':
  114 + raise template.TemplateSyntaxError("second argument to '%s' tag must be 'as'" % bits[0])
  115 + return ScoresForObjectsNode(bits[1], bits[3])
  116 +
88 117 def do_vote_by_user(parser, token):
89 118 """
90 119 Retrieves the ``Vote`` cast by a user on a particular object and
@@ -140,6 +169,7 @@ def do_vote_for_item(parser, token):
140 169 return VoteForItemNode(bits[1], bits[3], bits[5])
141 170
142 171 register.tag('score_for_object', do_score_for_object)
  172 +register.tag('scores_for_objects', do_scores_for_objects)
143 173 register.tag('vote_by_user', do_vote_by_user)
144 174 register.tag('votes_by_user', do_votes_by_user)
145 175 register.tag('vote_for_item', do_vote_for_item)

0 comments on commit 6e2e9aa

Please sign in to comment.
Something went wrong with that request. Please try again.