Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #24 — corrects get_scores_in_bulk to work on both 1.0 and 1.1

This patch is based on the work from jsmullyan (thanks!) and improves it
slightly to match the 1.0 SQL.

git-svn-id: https://django-voting.googlecode.com/svn/trunk@70 662f01ad-f42a-0410-a340-718c64ddaef4
  • Loading branch information...
commit 8215b14cdca90f4ec49c50b3573bccbbdfb2ebc1 1 parent a899a7b
@brosner authored
Showing with 62 additions and 9 deletions.
  1. +62 −9 voting/managers.py
View
71 voting/managers.py
@@ -1,7 +1,40 @@
from django.conf import settings
from django.db import connection, models
+
+try:
+ from django.db.models.sql.aggregates import Aggregate
+except ImportError:
+ supports_aggregates = False
+else:
+ supports_aggregates = True
+
from django.contrib.contenttypes.models import ContentType
+if supports_aggregates:
+ class CoalesceWrapper(Aggregate):
+ sql_template = 'COALESCE(%(function)s(%(field)s), %(default)s)'
+
+ def __init__(self, lookup, **extra):
+ self.lookup = lookup
+ self.extra = extra
+
+ def _default_alias(self):
+ return '%s__%s' % (self.lookup, self.__class__.__name__.lower())
+ default_alias = property(_default_alias)
+
+ def add_to_query(self, query, alias, col, source, is_summary):
+ super(CoalesceWrapper, self).__init__(col, source, is_summary, **self.extra)
+ query.aggregate_select[alias] = self
+
+
+ class CoalesceSum(CoalesceWrapper):
+ sql_function = 'SUM'
+
+
+ class CoalesceCount(CoalesceWrapper):
+ sql_function = 'COUNT'
+
+
class VoteManager(models.Manager):
def get_score(self, obj):
"""
@@ -32,16 +65,36 @@ def get_scores_in_bulk(self, objects):
ctype = ContentType.objects.get_for_model(objects[0])
ctype = ContentType.objects.get_for_model(objects[0])
- queryset = self.filter(
- object_id__in=object_ids, content_type=ctype).extra(
- select={
- 'score': 'COALESCE(SUM(vote), 0)',
- 'num_votes': 'COALESCE(COUNT(vote), 0)',
- }).values_list('object_id', 'score', 'num_votes')
- queryset.query.group_by.append('object_id')
+
+ if supports_aggregates:
+ queryset = self.filter(
+ object_id__in = object_ids,
+ content_type = ctype,
+ ).values(
+ 'object_id',
+ ).annotate(
+ score = CoalesceSum('vote', default='0'),
+ num_votes = CoalesceCount('vote', default='0'),
+ )
+ else:
+ queryset = self.filter(
+ object_id__in = object_ids,
+ content_type = ctype,
+ ).extra(
+ select = {
+ 'score': 'COALESCE(SUM(vote), 0)',
+ 'num_votes': 'COALESCE(COUNT(vote), 0)',
+ }
+ ).values('object_id', 'score', 'num_votes')
+ queryset.query.group_by.append('object_id')
+
vote_dict = {}
- for id, score, num_votes in queryset:
- vote_dict[id] = {'score': int(score), 'num_votes': int(num_votes)}
+ for row in queryset:
+ vote_dict[row['object_id']] = {
+ 'score': int(row['score']),
+ 'num_votes': int(row['num_votes']),
+ }
+
return vote_dict
def record_vote(self, obj, user, vote):
Please sign in to comment.
Something went wrong with that request. Please try again.