Commit d513882d by Alex Gaynor

Preload related tags.

parent 56e1227f
from collections import defaultdict
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.db.models.fields.related import ManyToManyRel from django.db.models.fields.related import ManyToManyRel
...@@ -137,9 +139,26 @@ class _TaggableManager(models.Manager): ...@@ -137,9 +139,26 @@ class _TaggableManager(models.Manager):
@require_instance_manager @require_instance_manager
def similar_objects(self): def similar_objects(self):
return TaggedItem.objects.values('object_id', 'content_type') \ qs = TaggedItem.objects.values('object_id', 'content_type') \
.annotate(models.Count('pk')) \ .annotate(n=models.Count('pk')) \
.exclude(object_id=self.object_id) \ .exclude(object_id=self.object_id) \
.filter(tag__in=self.all()) \ .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): ...@@ -90,6 +90,6 @@ class SimilarityByTagTestCase(BaseTaggingTest):
watermelon = Food.objects.create(name="watermelon") watermelon = Food.objects.create(name="watermelon")
watermelon.tags.add("green", "juicy", "large", "sweet") watermelon.tags.add("green", "juicy", "large", "sweet")
self.assertEqual(apple.tags.similar_objects(), similar_objs = apple.tags.similar_objects()
[{'pk__count': 3, 'content_type': 13, 'object_id': 6}, {'pk__count': 2, 'content_type': 13, 'object_id': 7}]) 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