Commit aa961dd9 by Rob Hudson

Added manager method `similar_objects`.

This finds similar objects that have the most tags in common.
parent 805389ac
...@@ -136,3 +136,12 @@ class _TaggableManager(models.Manager): ...@@ -136,3 +136,12 @@ class _TaggableManager(models.Manager):
return self.get_query_set().annotate( return self.get_query_set().annotate(
num_times=models.Count('items') num_times=models.Count('items')
).order_by('-num_times') ).order_by('-num_times')
@require_instance_manager
def similar_objects(self):
return TaggedItem.objects.values('object_id', 'content_type') \
.annotate(models.Count('pk')) \
.exclude(object_id=self.object_id) \
.filter(tag__in=self.all()) \
.order_by('-pk__count')
from taggit.tests.tests import AddTagTestCase, LookupByTagTestCase, TaggableFormTestCase from taggit.tests.tests import AddTagTestCase, LookupByTagTestCase, TaggableFormTestCase, SimilarityByTagTestCase
...@@ -79,3 +79,19 @@ class TaggableFormTestCase(BaseTaggingTest): ...@@ -79,3 +79,19 @@ class TaggableFormTestCase(BaseTaggingTest):
apple = Food.objects.get(name='apple') apple = Food.objects.get(name='apple')
self.assert_tags_equal(apple.tags.all(), ['green', 'red', 'yummy', 'delicious']) self.assert_tags_equal(apple.tags.all(), ['green', 'red', 'yummy', 'delicious'])
self.assertEqual(Food.objects.count(), 1) self.assertEqual(Food.objects.count(), 1)
class SimilarityByTagTestCase(BaseTaggingTest):
def test_similarity_by_tag(self):
"""Test that pears are more similar to apples than watermelons"""
apple = Food.objects.create(name="apple")
apple.tags.add("green", "juicy", "small", "sour")
pear = Food.objects.create(name="pear")
pear.tags.add("green", "juicy", "small", "sweet")
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}])
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