Возможно ли фильтровать поля набора запросов 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()
)
Вернуться на верх