Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ManyToManyField exclude

I'm very new to Django, being a C guy (embedded/Linux) for the most part, so I apologize for my ignorance. I've tried searching for this exact query with no luck.

I have two Models, each of which has a many-to-many field pointing to the same third Model. This third model represents a restriction of some kind.

class Restriction(models.Model):
    ...

class ClassA(models.Model):
    ...
    restrictions = models.ManyToManyField(Restriction)

class ClassB(models.Model):
    ...
    restrictions = models.ManyToManyField(Restriction)

I anticipate having an instance of ClassA (call it object_a). I'd like to find all instances of ClassB which do not contain any of the restrictions in object_a. It would look something like this:

class ClassA(models.Model):
    ...
    restrictions = models.ManyToManyField(Restriction)

    def get_valid_b_objects():
        return ClassB.objects.exclude(restrictions__in=self.restrictions)

But this doesn't feel right. Again, if any of the restrictions in a ClassB object is also in my ClassA object, that instance of ClassB should be excluded from the query. So, if:

  • object_a contains restrictions 1, 2, and 3
  • object_b1 contains restrictions 2, 4, and 5
  • object_b2 contains restrictions 1 and 2
  • object_b3 contains restrictions 1, 2, 3, 4, and 5
  • object_b4 contains restrictions 4 and 5
  • object_b5 contains restriction 5
  • object_b6 contains no restrictions

Then object_a.get_valid_b_objects() should return object_b4, object_b5, and object_b6.

Thank you very much. Feel free to direct me to another answer if this has already been addressed.

like image 475
kofdog Avatar asked May 28 '17 20:05

kofdog


1 Answers

What you have should work. Just make sure you use an actual QuerySet, not the related manager:

# don't forget '.all()'
return ClassB.objects.exclude(restrictions__in=self.restrictions.all())

This will exclude any B instance that has any of the A instance's restrictions.

like image 165
user2390182 Avatar answered Oct 20 '22 10:10

user2390182