Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
Jonny Buchanan insin authored
Showing with 71 additions and 1 deletion.
  1. +17 −0 README.txt
  2. +24 −1 models.py
  3. +30 −0 templatetags/voting_tags.py
17 README.txt
View
@@ -79,6 +79,12 @@ functions:
Returns a dictionary with ``score`` and ``num_votes`` keys.
+ * ``get_scores_in_bulk(objects)`` -- Gets score and vote count
+ details for all the given objects. Score details consist of a
+ dictionary which has ``score`` and ``num_vote`` keys.
+
+ Returns a dictionary mapping object ids to score details.
+
* ``get_top(Model, limit=10, reversed=False)`` -- Gets the top
``limit`` scored objects for a given model.
@@ -312,6 +318,17 @@ Example usage::
{{ score.score }} point{{ score.score|pluralize }}
after {{ score.num_votes }} vote{{ score.num_votes|pluralize }}
+scores_for_objects
+~~~~~~~~~~~~~~~~~~
+
+Retrieves the total scores and number of votes cast for a list of
+objects as a dictionary keyed with the objects' ids and stores it in a
+context variable.
+
+Example usage::
+
+ {% scores_for_objects widget_list as scores %}
+
vote_by_user
~~~~~~~~~~~~
25 models.py
View
@@ -1,4 +1,4 @@
-from django.db import models, connection
+from django.db import backend, connection, models
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
@@ -17,6 +17,29 @@ def get_score(self, obj):
result = cursor.fetchall()[0]
return {'score': result[0] or 0, 'num_votes': result[1]}
+ def get_scores_in_bulk(self, objects):
+ """
+ Get a dictionary mapping object ids to total score and number
+ of votes for each object.
+ """
+ query = """
+SELECT object_id, SUM(vote), COUNT(vote)
+FROM %s
+WHERE content_type_id = %%s
+ AND object_id IN (%s)
+GROUP BY object_id""" % (
+ backend.quote_name(self.model._meta.db_table),
+ ','.join(['%s'] * len(objects))
+ )
+ ctype = ContentType.objects.get_for_model(objects[0])
+ cursor = connection.cursor()
+ cursor.execute(query, [ctype.id] + [obj.id for obj in objects])
+ results = cursor.fetchall()
+ return dict([(object_id, {
+ 'score': score,
+ 'num_votes': num_votes,
+ }) for object_id, score, num_votes in results])
+
def record_vote(self, obj, user, vote):
"""
Record a user's vote on a given object. Only allows a given user
30 templatetags/voting_tags.py
View
@@ -20,6 +20,19 @@ def render(self, context):
context[self.context_var] = Vote.objects.get_score(self.object)
return ''
+class ScoresForObjectsNode(template.Node):
+ def __init__(self, objects, context_var):
+ self.objects = objects
+ self.context_var = context_var
+
+ def render(self, context):
+ try:
+ objects = template.resolve_variable(self.objects, context)
+ except template.VariableDoesNotExist:
+ return ''
+ context[self.context_var] = Vote.objects.get_scores_in_bulk(objects)
+ return ''
+
class VoteByUserNode(template.Node):
def __init__(self, user, object, context_var):
self.user = user
@@ -85,6 +98,22 @@ def do_score_for_object(parser, token):
raise template.TemplateSyntaxError("second argument to '%s' tag must be 'as'" % bits[0])
return ScoreForObjectNode(bits[1], bits[3])
+def do_scores_for_objects(parser, token):
+ """
+ Retrieves the total scores for a list of objects and the number of
+ votes they have received and stores them in a context variable.
+
+ Example usage::
+
+ {% scores_for_objects widget_list as score_dict %}
+ """
+ bits = token.contents.split()
+ if len(bits) != 4:
+ raise template.TemplateSyntaxError("'%s' tag takes exactly three arguments" % bits[0])
+ if bits[2] != 'as':
+ raise template.TemplateSyntaxError("second argument to '%s' tag must be 'as'" % bits[0])
+ return ScoresForObjectsNode(bits[1], bits[3])
+
def do_vote_by_user(parser, token):
"""
Retrieves the ``Vote`` cast by a user on a particular object and
@@ -140,6 +169,7 @@ def do_vote_for_item(parser, token):
return VoteForItemNode(bits[1], bits[3], bits[5])
register.tag('score_for_object', do_score_for_object)
+register.tag('scores_for_objects', do_scores_for_objects)
register.tag('vote_by_user', do_vote_by_user)
register.tag('votes_by_user', do_votes_by_user)
register.tag('vote_for_item', do_vote_for_item)
Please sign in to comment.
Something went wrong with that request. Please try again.