web-dev-qa-db-fra.com

Django filtre plusieurs-à-plusieurs avec contient

J'essaie de filtrer un tas d'objets à travers une relation plusieurs-à-plusieurs. Parce que le champ trigger_roles peut contenir plusieurs entrées, j'ai essayé le filtre contient. Mais comme cela est conçu pour être utilisé avec des chaînes, je suis à peu près incapable de filtrer cette relation (vous pouvez ignorer l'atmosphère values_list ().).

Cette fonction est attachée au profil utilisateur:

def getVisiblePackages(self):
    visiblePackages = {}   
    for product in self.products.all():
        moduleDict = {}
        for module in product.module_set.all():
            pkgList = []
            involvedStatus = module.workflow_set.filter(trigger_roles__contains=self.role.id,allowed=True).values_list('current_state', flat=True)

Mon modèle de workflow ressemble à ceci (simplifié):

class Workflow(models.Model):
    module = models.ForeignKey(Module)
    current_state = models.ForeignKey(Status)
    next_state = models.ForeignKey(Status)
    allowed = models.BooleanField(default=False)
    involved_roles = models.ManyToManyField(Role, blank=True, null=True)
    trigger_roles = models.ManyToManyField(Role, blank=True, null=True)

Bien que la solution soit simple, mon cerveau ne me le dira pas.

Merci de votre aide.

66
Grave_Jumper

Avez-vous essayé quelque chose comme ça:

module.workflow_set.filter(trigger_roles__in=[self.role], allowed=True)

ou juste si self.role.id n'est pas une liste de pks:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True)
88
mouad

L'approche la plus simple pour y parvenir serait de vérifier l'équité sur toute l'instance (au lieu de l'id) dans le ManyToManyField. Cela regarde si l'instance est dans la relation plusieurs à plusieurs. Exemple:

module.workflow_set.filter(trigger_roles=self.role, allowed=True)
15
Caumons

la singularité est presque exacte avec le premier exemple. Vous devez juste vous assurer qu'il s'agit d'une liste. Le deuxième exemple, la vérification de trigger_roles__id__exact est cependant une meilleure solution.

module.workflow_set.filter(trigger_roles__in=[self.role.id],allowed=True)
4
Josh Smeaton

Je sais que c'est une vieille question, mais il semble que le PO n'ait jamais tout à fait obtenu la réponse qu'il cherchait. Si vous souhaitez comparer deux ensembles de ManyToManyFields, l'astuce consiste à utiliser l'opérateur __in, Et non contains. Ainsi, par exemple, si vous avez un modèle "Event" avec un ManyToMany à "Group" sur le champ eventgroups, et que votre modèle utilisateur se rattache (évidemment) au groupe, vous pouvez interroger comme ceci:

Event.objects.filter(eventgroups__in=u.groups.all())

3
shacker