2017-08-14 1 views
0

Je voudrais filter un modèle Django qui est connecté à un second modèle via une relation intermédiaire plusieurs-à-plusieurs.django filtre plusieurs-à-plusieurs avec liste donnée

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) 

design and expected result

Le résultat devrait être de ne sélectionner que la personne A parce qu'il est connecté à des groupes avec des entrées 1 et 2 par les membres. Je voudrais utiliser Q objets pour ce genre de tâche.

Quelqu'un peut-il me donner un indice?

Répondre

1

Je pense que vous voulez que tous les objets Person qui sont dans tous les GID.

Solution:

from django.db.models import Q 

person_qs = Person.objects.exclude(~(Q(group__id=1) & Q(group__id=2))) 

Ici, j'utilisé exclude d'exclure tous les GID qui ne sont pas 1 et 2.

Si vous avez beaucoup de GID, vous pouvez utiliser reduce et operator pour générer la requête dans une seule boucle for.

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) 

Ceci formera la requête comme Q(group__id=1) & Q(group_id=2) & (ainsi de suite ...)

+0

C'est exactement ce que je cherchais! Merci beaucoup! – essin

2

Il n'y a pas besoin d'utiliser Q ici, c'est une requête simple. vous lui fournir à

Person.objects.filter(group__id__in=[1, 2]) 
+0

Mais cela retournerait B aswell correctes, IN agit comme OU? – essin