Возможно ли фильтровать поля набора запросов django Many-To-Many, проверяя, не является ли их пересечение пустым?
Выполняю упражнение о создании Django-сервиса, который при заданном задании возвращает лучших кандидатов. Конечно, это проблема машинного обучения, и алгоритм скоринга здесь очень простой. Честно говоря, это первый раз, когда я использую Django, и у меня возникли некоторые проблемы с фильтрацией объектов из одной из моделей.
Это мой класс модели:
from django.db import models
class Skill(models.Model):
name = models.CharField(max_length=100)
def __str__(self) -> str:
return f'Skill name: {self.name}'
class Candidate(models.Model):
title = models.CharField(max_length=100)
name = models.CharField(max_length=100, default='')
skills = models.ManyToManyField(Skill)
def __str__(self) -> str:
return f'Name: {self.name}, title: {self.title}'
class Job(models.Model):
title = models.CharField(max_length=100)
skills = models.ManyToManyField(Skill)
def __str__(self) -> str:
return f'title: {self.title}'
Сначала я хотел бы отфильтровать вакансию по навыкам, т.е. перебрать всех кандидатов и отсеять тех, у кого нет общих навыков с данной вакансией. В более математическом подходе - пересечение набора_навыков_работы и набора_навыков_кандидата не является пустым. Что-то вроде этого: (я смешал синтаксис Python)
Candidate.objects.filter(len(set.intersection(set(skills), set(job.skills))) > 0)
Есть ли способ сделать это в Django? Пробовал несколько способов и не преуспел.
Заранее спасибо!
Чтобы получить всех кандидатов, имеющих хотя бы один общий навык с данной вакансией, можно просто проследить взаимосвязь по всей таблице навыков
Candidate.objects.filter(skills__job=job).distinct()
Чтобы получить кандидатов, обладающих всеми теми же навыками, что и в вакансии, можно подсчитать количество совпадений, а затем отфильтровать кандидатов, у которых количество совпадает с количеством навыков
from django.db.models import Count
Candidate.objects.filter(
skills__job=job
).annotate(
match=Count('skills')
).filter(
match=job.skills.count()
)