Commit d513882d by Alex Gaynor

Preload related tags.

parent 56e1227f
from collections import defaultdict
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models.fields.related import ManyToManyRel
......@@ -137,9 +139,26 @@ class _TaggableManager(models.Manager):
@require_instance_manager
def similar_objects(self):
return TaggedItem.objects.values('object_id', 'content_type') \
.annotate(models.Count('pk')) \
qs = TaggedItem.objects.values('object_id', 'content_type') \
.annotate(n=models.Count('pk')) \
.exclude(object_id=self.object_id) \
.filter(tag__in=self.all()) \
.order_by('-pk__count')
.order_by('-n')
preload = defaultdict(set)
for result in qs:
preload[result["content_type"]].add(result["object_id"])
items = {}
for ct, obj_ids in preload.iteritems():
ct = ContentType.objects.get_for_id(ct)
items[ct.pk] = dict((o.pk, o) for o in
ct.model_class()._default_manager.filter(pk__in=obj_ids)
)
results = []
for result in qs:
obj = items[result["content_type"]][result["object_id"]]
obj.similar_tags = result["n"]
results.append(obj)
return results
......@@ -90,6 +90,6 @@ class SimilarityByTagTestCase(BaseTaggingTest):
watermelon = Food.objects.create(name="watermelon")
watermelon.tags.add("green", "juicy", "large", "sweet")
self.assertEqual(apple.tags.similar_objects(),
[{'pk__count': 3, 'content_type': 13, 'object_id': 6}, {'pk__count': 2, 'content_type': 13, 'object_id': 7}])
similar_objs = apple.tags.similar_objects()
self.assertEqual(similar_objs, [pear, watermelon])
self.assertEqual(map(lambda x: x.similar_tags, similar_objs), [3, 2])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment