如何在django taggit中显示与特定标签相关的标签?

时间:2011-08-11 05:59:17

标签: django django-taggit

我想显示与特定标记相关的标记列表(以优化的方式)。 我想知道为什么django-taggit没有为这个常见任务提供内置功能。<​​/ p>

1 个答案:

答案 0 :(得分:4)

我提供的解决方案比你要求的解决方案多一点,因为它允许为一组给定的标签找到相关的标签,而不仅仅是一个给定的标签。实际上,这可能是你想要做的。我不确定它在性能方面是否真的是最佳的,因为它使用子查询,但它有效,我觉得它很容易理解。

首先,这是测试用例:

from django.test import TestCase
from .models import Item, get_related_tags


class RelatedTagsTest(TestCase):

    def setUp(self):
        article1 = Item.objects.create(title='Python vs. COBOL')
        article1.tags.add('programming', 'python', 'cobol')
        article2 = Item.objects.create(title='Python vs. Boa Constrictor')
        article2.tags.add('zoology', 'python', 'boa')
        article3 = Item.objects.create(title='COBOL vs. FORTRAN')
        article3.tags.add('cobol', 'fortran', 'programming')

    def test_unique_tag(self):
        self.assertEquals(get_related_tags('programming'),
                          ['cobol', 'fortran', 'python'])
        self.assertEquals(get_related_tags('python'),
                          ['boa', 'cobol', 'programming', 'zoology'])

    def test_multiple_tags(self):
        self.assertEquals(get_related_tags('boa', 'fortran'),
                          ['cobol', 'programming', 'python', 'zoology'])

正如您所看到的,“相关标签”是指与标记有一组给定标签的项目相关联的标签集。

这是我们的模型,它具有获取相关标签的功能:

from django.db import models
from taggit.managers import TaggableManager
from taggit.models import Tag

class Item(models.Model):
    title = models.CharField(max_length=100)
    tags = TaggableManager()


def get_related_tags(*tags):
    # Get a QuerySet of related items
    related_items = Item.objects.filter(tags__name__in=tags)

    # Get tags for those related items (I found the name of the lookup field by
    # reading taggit's source code)
    qs = Tag.objects.filter(taggit_taggeditem_items__item__in=related_items)

    # Exclude the tags we already have
    qs = qs.exclude(name__in=tags)

    # Order by name and remove duplicates
    qs = qs.order_by('name').distinct()

    # Return tag names to simplify test code, real code would probably return
    # Tag objects
    return [t.name for t in qs]

请注意,您可以使用qs.annotate(count=Count('name'))轻松添加每个代码的项目数。它将作为每个count对象的Tag属性提供。