简体   繁体   中英

Django: How to query objects where manytomany fields ALL exist in a list?

I would like to grab the programs where ALL the related prereq_courses exist in a provided list (called course_codes). So I do not want the programs that contain prereq_courses that do not exist in that list. How do I do that?

models.py

class Course(models.Model):
    name = models.CharField(max_length=255, blank=True)
    code = models.CharField(max_length=64, blank=True, unique=True)

class Prerequisite(models.Model):
    program = models.ForeignKey('Program', on_delete=models.CASCADE)
    course = models.ForeignKey('Course', on_delete=models.CASCADE, null=True)
    group = models.IntegerField(null=True, default=0)

class Program(models.Model):
    name = models.CharField(max_length=255)
    prereq_courses = models.ManyToManyField(Course, through=Prerequisite)

I tried the following, but it also gave me programs that include prereq_courses that do not exist in the course_codes list.

for code in course_codes: 
    eligible_progs = eligible_progs.filter(prereq_courses__code=code)

There is the in field lookup in django which transforms into the IN operator in SQL :

eligible_programs = eligible_progs.filter(prereq_courses__course__code__in=course_codes)

You should also notice, that by using __ you tell django ORM to join tables behind the scenes, if the models property is a ForeignKeyField .

I found the solution in the docs

In order to test for the existence of ALL courses in a list, I basically had to do it in reverse. So first, I got a query set of all the UNTAKEN courses. Then I excluded the programs that have prerequisite courses that are part of the untaken courses query set. I added another parameter and so I had to use the filter() operation. It worked like a charm.

not_taken_courses = Course.objects.exclude(code__in=course_codes)

eligible_programs = eligible_progs.exclude( 
     prerequisite__in=Prerequisite.objects.filter( 
        course__in=not_taken_courses, relation_type = "Alone", 
     ), 
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM