Reputation: 3
I would like to filter
a Django model that is connected to a second model via a many-to-many intermediate relationship.
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
The result should be to select only Person A because he is connected to Groups with entries 1 AND 2 through the membership. I'd like to use Q
objects for this kind of task.
Can anyone give me a hint?
Upvotes: 0
Views: 3800
Reputation: 3674
I think you want all the Person
objects which are in all the group Ids you will provide it to.
Solution:
from django.db.models import Q
person_qs = Person.objects.exclude(~(Q(group__id=1) & Q(group__id=2)))
Here, I used exclude
to exclude all the group Ids which are not 1 and 2.
If you have lots of group Ids, you can use reduce
and operator
to build the query in a single for-loop.
from functools import reduce
import operator
query = reduce(operator.and_, (Q(group__id=group_id) for group_id in group_ids))
persons_qs = Person.objects.exclude(~query)
This, will form the query like Q(group__id=1) & Q(group_id=2) &
(so on...)
Upvotes: 6
Reputation: 600041
There's no need to use Q here, it is a simple query.
Person.objects.filter(group__id__in=[1, 2])
Upvotes: 1