Skip to content

Instantly share code, notes, and snippets.

@nathanborror
Created February 1, 2010 04:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathanborror/291454 to your computer and use it in GitHub Desktop.
Save nathanborror/291454 to your computer and use it in GitHub Desktop.
diff --git a/taggit/managers.py b/taggit/managers.py
index a751e21..918d256 100644
--- a/taggit/managers.py
+++ b/taggit/managers.py
@@ -2,7 +2,7 @@ from collections import defaultdict
import django
from django.contrib.contenttypes.models import ContentType
-from django.db import models
+from django.db import models, connection
from django.db.models.fields.related import ManyToManyRel
from django.db.models.query_utils import QueryWrapper
@@ -175,3 +175,67 @@ class _TaggableManager(models.Manager):
obj.similar_tags = result["n"]
results.append(obj)
return results
+
+ def _get_usage(self, model, counts=False, min_count=None, extra_joins=None, extra_criteria=None, params=None):
+ """
+ Perform the custom SQL query for ``usage_for_model`` and
+ ``usage_for_queryset``.
+ """
+ if min_count is not None: counts = True
+
+ qn = connection.ops.quote_name
+ model_table = qn(model._meta.db_table)
+ model_pk = '%s.%s' % (model_table, qn(model._meta.pk.column))
+ query = """
+ SELECT DISTINCT %(tag)s.id, %(tag)s.name%(count_sql)s
+ FROM
+ %(tag)s
+ INNER JOIN %(tagged_item)s
+ ON %(tag)s.id = %(tagged_item)s.tag_id
+ INNER JOIN %(model)s
+ ON %(tagged_item)s.object_id = %(model_pk)s
+ %%s
+ WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
+ %%s
+ GROUP BY %(tag)s.id, %(tag)s.name
+ %%s
+ ORDER BY %(tag)s.name ASC""" % {
+ 'tag': qn(Tag._meta.db_table),
+ 'count_sql': counts and (', COUNT(%s)' % model_pk) or '',
+ 'tagged_item': qn(TaggedItem._meta.db_table),
+ 'model': model_table,
+ 'model_pk': model_pk,
+ 'content_type_id': ContentType.objects.get_for_model(model).pk,
+ }
+
+ min_count_sql = ''
+ if min_count is not None:
+ min_count_sql = 'HAVING COUNT(%s) >= %%s' % model_pk
+ params.append(min_count)
+
+ cursor = connection.cursor()
+ cursor.execute(query % (extra_joins, extra_criteria, min_count_sql), params)
+ tags = []
+ for row in cursor.fetchall():
+ t = Tag.objects.get(pk=row[0])
+ if counts:
+ t.count = row[2]
+ tags.append(t)
+ return tags
+
+ def filter(self, queryset, counts=False, min_count=None):
+ """
+ Return a list of tags associated with instances of a model
+ contained within a given queryset.
+ """
+ if getattr(queryset.query, 'get_compiler', None):
+ compiler = queryset.query.get_compiler(using='default')
+ extra_joins = ' '.join(compiler.get_from_clause()[0][1:])
+ where, params = queryset.query.where.as_sql(
+ compiler.quote_name_unless_alias, compiler.connection
+ )
+ if where:
+ extra_criteria = 'AND %s' % where
+ else:
+ extra_criteria = ''
+ return self._get_usage(queryset.model, counts, min_count, extra_joins, extra_criteria, params)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment