#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]
Логика выглядит следующим образом:
current_project
это экземпляр проекта, для которого вы хотите установить отношения.filter
выбирает все проекты, у которых есть теги, совпадающие с текущим проектом.annotate
Добавляет переменную к возвращаемым значениям, которая подсчитывает количество похожих имен. Поскольку проекты, соответствующие нескольким тегам, возвращаются несколько раз, это значение указывает на количество совпадений.- Результаты сортируются по аннотированной
name__count
переменной. Чтобы получить 3 лучших результата, список ограничен с помощью[:3]
.
Комментарии:
1. И поместите это в атрибут
Project
класса. Заменитьcurrent_project
наself
, конечно.2. Спасибо!! работал почти идеально. одна маленькая важная вещь, чтобы заставить его работать:
from django.db.models import Count