Как получить похожие проекты на основе тегов в Django

#python #django #django-orm

#python #django #django-orm

Вопрос:

В моем приложении есть модели Project и Tag с отношением «многие ко многим» между ними. На странице каждого проекта я хочу перечислить 3 дополнительных проекта, которые имеют наибольшее количество общих тегов с ним. Как я могу выполнить этот запрос?

 class Tag(models.Model):
  name = models.CharField(max_length=300)

class Project(models.Model):
  name = models.CharField(max_length=300)
  ...
  tags = models.ManyToManyField(Tag)
  

Ответ №1:

Можно упаковать все это в одну строку:

 Project.objects.filter(tags__in=current_project.tags.all()).annotate(Count('name')).order_by('-name__count')[:3]
  

Или с разбивкой по шагам:

 tags = current_project.tags.all()
matches = Project.objects.filter(tags__in=tags).annotate(Count('name'))
results = matches.order_by('-name__count')[:3]
  

Логика выглядит следующим образом:

  1. current_project это экземпляр проекта, для которого вы хотите установить отношения.
  2. filter выбирает все проекты, у которых есть теги, совпадающие с текущим проектом.
  3. annotate Добавляет переменную к возвращаемым значениям, которая подсчитывает количество похожих имен. Поскольку проекты, соответствующие нескольким тегам, возвращаются несколько раз, это значение указывает на количество совпадений.
  4. Результаты сортируются по аннотированной name__count переменной. Чтобы получить 3 лучших результата, список ограничен с помощью [:3] .

Комментарии:

1. И поместите это в атрибут Project класса. Заменить current_project на self , конечно.

2. Спасибо!! работал почти идеально. одна маленькая важная вещь, чтобы заставить его работать: from django.db.models import Count