Я довольно озадачен лучшим способом создания Django-запроса, который проверяет, присутствуют ли все элементы поля ManyToMany
(или список) в другом поле ManyToMany
.
В качестве примера у меня есть несколько Person
s, у которых может быть более одной Specialty. Есть также Job
, которые могут запускаться людьми, но для их запуска требуется один или несколько Specialty
.
class Person(models.Model):
name = models.CharField()
specialties = models.ManyToManyField('Specialty')
class Specialty(models.Model):
name = models.CharField()
class Job(models.Model):
required_specialties = models.ManyToManyField('Specialty')
Человек может начать работу только в том случае, если у них есть все специальности, требуемые работой. Итак, опять же, для примера, у нас есть три специальности:
- Кодирование
- Пение
- Танцы
И у меня есть Job
, который требует специальностей поющего и танцующего. Человек с пением и танцевальными специальностями может начать его, но другой с навыками кодирования и пения не может - поскольку Иов требует Человека, который может петь и танцевать.
Итак, теперь мне нужен способ найти все задания, которые человек может принять. Это был мой способ справиться с этим, но я уверен, что есть более элегантный подход:
def jobs_that_person_can_start(person):
# we start with all jobs
jobs = Job.objects.all()
# find all specialties that this person does not have
specialties_not_in_person = Specialty.objects.exclude(name__in=[s.name for s in person.specialties])
# and exclude jobs that require them
for s in specialties_not_in_person:
jobs = jobs.exclude(specialty=s)
# the ones left should fill the criteria
return jobs.distinct()
Это связано с тем, что использование Job.objects.filter(specialty__in=person.specialties.all())
будет возвращать задания, соответствующие любым специальностям человека, а не все из них. Используя этот запрос, для пения-кодера появится работа, требующая пения и танца, которая не является желаемым выходом.
Я надеюсь, что этот пример не слишком запутан. Причина, по которой я беспокоюсь об этом, заключается в том, что Specialities в системе, вероятно, будет намного больше, и переключение по ним не похоже на лучший способ достичь этого. Мне интересно, сможет ли кто-нибудь приложить царапину к этому зуду!