Comment interroger correctement un ManyToManyField pour tous les objets dans une liste (ou un autre ManyToManyField)?

Je suis plutôt perplexe quant à la meilleure façon de construire un Django requête qui vérifie si tous les éléments d'une ManyToMany champ (ou une liste) sont présents dans un autre ManyToMany champ.

Comme un exemple, j'ai plusieurs Persons, qui peut avoir plus d'une Spécialité. Il y a aussi des Jobs que les gens peuvent commencer, mais ils nécessitent une ou plusieurs Specialtys pour être admissible à être démarré.

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')

Une personne peut commencer un travail seulement si ils ont tous les spécialités que le travail exige. Donc, encore une fois par souci d'exemple, nous avons trois spécialités:

  • Codage
  • Chant
  • Danse

Et j'ai un Job qui nécessite le Chant et la Danse spécialités. Une personne avec des Chants et de la Danse spécialités pouvez le démarrer, mais une autre avec le Codage et le Chant des spécialités qui ne peut pas -- que le Poste exige une Personne qui peut à la fois chanter et danser.

Alors, maintenant, j'ai besoin d'un moyen de trouver tous les emplois qu'une personne peut prendre. C'était ma façon de l'aborder, mais je suis sûre qu'il y a de plus élégant approche:

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()

C'est parce que l'utilisation de Job.objects.filter(specialty__in=person.specialties.all()) sera de retour un emploi qui correspond à tout de la personne spécialités, pas tous d'entre eux. À l'aide de cette requête, le travail qui exige de Chant et de Danse semble pour le chant codeur, ce qui n'est pas le résultat souhaité.

J'espère que cet exemple n'est pas trop compliquée à comprendre. La raison pour laquelle je m'inquiète c'est que les Spécialités dans le système sera probablement beaucoup plus, et en boucle sur eux ne semble pas être le meilleur moyen d'y parvenir. Je me demandais si quelqu'un pourrait donner un zéro pour cette démangeaison!

OriginalL'auteur rlafuente | 2009-12-03