From 6ba1659e33c6aa1de178b5ab9a7a4cf27385e7a4 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 24 Jan 2012 13:06:37 +0100 Subject: [PATCH 1/1] better related books --- apps/catalogue/templatetags/catalogue_tags.py | 13 +++---------- apps/newtagging/managers.py | 8 +++++--- apps/newtagging/models.py | 14 +++++++++++++- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/catalogue/templatetags/catalogue_tags.py b/apps/catalogue/templatetags/catalogue_tags.py index 583c9c763..2254299d5 100644 --- a/apps/catalogue/templatetags/catalogue_tags.py +++ b/apps/catalogue/templatetags/catalogue_tags.py @@ -345,16 +345,9 @@ def related_books(book, limit=6): common_slug=book.common_slug).exclude(pk=book.pk)[:limit]) limit -= len(related) if limit: - tagged = Book.tagged.with_any(book.tags).exclude(pk=book.pk) - book_tag = book.book_tag() - for rel_book in tagged: - if book_tag in rel_book.tags.all(): - continue - related += [rel_book] - limit -= 1 - if not limit: - break - + related += Book.tagged.related_to(book, + Book.objects.exclude(common_slug=book.common_slug), + ignore_by_tag=book.book_tag())[:limit] return { 'books': related, } diff --git a/apps/newtagging/managers.py b/apps/newtagging/managers.py index 3107070ea..f802aa1cb 100644 --- a/apps/newtagging/managers.py +++ b/apps/newtagging/managers.py @@ -35,11 +35,13 @@ class ModelTaggedItemManager(models.Manager): super(ModelTaggedItemManager, self).__init__() self.intermediary_table_model = tag_model.objects.intermediary_table_model - def related_to(self, obj, queryset=None, num=None): + def related_to(self, obj, queryset=None, num=None, ignore_by_tag=None): if queryset is None: - return self.intermediary_table_model.objects.get_related(obj, self.model, num=num) + return self.intermediary_table_model.objects.get_related( + obj, self.model, num=num, ignore_by_tag=ignore_by_tag) else: - return self.intermediary_table_model.objects.get_related(obj, queryset, num=num) + return self.intermediary_table_model.objects.get_related( + obj, queryset, num=num, ignore_by_tag=ignore_by_tag) def with_all(self, tags, queryset=None): if queryset is None: diff --git a/apps/newtagging/models.py b/apps/newtagging/models.py index e9b114145..6d05e287e 100644 --- a/apps/newtagging/models.py +++ b/apps/newtagging/models.py @@ -439,7 +439,7 @@ class TaggedItemManager(models.Manager): else: return model._default_manager.none() - def get_related(self, obj, queryset_or_model, num=None): + def get_related(self, obj, queryset_or_model, num=None, ignore_by_tag=None): """ Retrieve a list of instances of the specified model which share tags with the model instance ``obj``, ordered by the number of @@ -447,6 +447,8 @@ class TaggedItemManager(models.Manager): If ``num`` is given, a maximum of ``num`` instances will be returned. + + If ``ignore_by_tag`` is given, object tagged with it will be ignored. """ queryset, model = get_queryset_and_model(queryset_or_model) model_table = qn(model._meta.db_table) @@ -466,6 +468,15 @@ class TaggedItemManager(models.Manager): # instances for the same model. query += """ AND related_tagged_item.object_id != %(tagged_item)s.object_id""" + if ignore_by_tag is not None: + query += """ + AND NOT EXISTS ( + SELECT * FROM %(tagged_item)s + WHERE %(tagged_item)s.object_id = %(model_pk)s + AND %(tagged_item)s.content_type_id = %(content_type_id)s + AND %(ignore_id)s = %(tagged_item)s.tag_id + ) + """ query += """ GROUP BY %(model_pk)s ORDER BY %(count)s DESC @@ -479,6 +490,7 @@ class TaggedItemManager(models.Manager): 'content_type_id': content_type.pk, 'related_content_type_id': related_content_type.pk, 'limit_offset': num is not None and connection.ops.limit_offset_sql(num) or '', + 'ignore_id': ignore_by_tag.id if ignore_by_tag else None, } cursor = connection.cursor() -- 2.20.1