Подсчет общих членов ManyToMany в наборе запросов
Предположим, что у меня есть такие модели:
class Bar(models.Model):
pass # some simple Model goes here
class Foo(models.Model):
bars = models.ManyToManyField(Bar)
При наличии некоторой переменной main_object = Foo() с заполненными bars, как я могу сделать Queryset так, чтобы он был аннотирован количеством общих bars элементов между каждой сущностью и main_object?
Пример:
Имеется три записи Bar, с первичными ключами 1, 2 и 3. main_object имеет pk=2 как набор членов в bars.
Foo имеет две записи: main_object и еще одна с pk=1, установленным в bars. В этом случае мне нужна аннотация, имеющая значение 0, поскольку указанная запись не имеет общих внешних ключей Bar с main_object.
Я могу представить нечто подобное Foo.objects.filter(bars__in=<some_values_here>), но вместо простой проверки наличия, фактически подсчитывая его, как from django.db.models.Count.
Решаема ли она вообще с помощью Querysets или я должен прибегнуть к ручному подсчету через циклы?
В практическом использовании такой способ запроса может быть полезен при ранжировании по сходству, но мне он кажется нетривиальным.
Вы можете считать с:
from django.db.models import Count, Q
Foo.objects.annotate(
common_count=Count(
'bars',
filter=Q(bars__foo=main_object)
)
)
или если вы хотите получить только те объекты, которые имеют хотя бы одно общее Bar:
Foo.objects.filter(
bars__foo=main_object
).distinct()