2010-12-22 20 views
49

Ich versuche, eine Reihe von Objekten durch eine Viele-zu-viele-Beziehung zu filtern. Da das trigger_roles-Feld mehrere Einträge enthalten kann, habe ich den contains-Filter ausprobiert. Aber da dies für die Verwendung mit Strings vorgesehen ist, bin ich ziemlich hilflos, wie ich diese Beziehung filtern sollte (Sie können die values_list() atm ignorieren.).Django Filter viele-zu-viele mit enthält

Diese Funktion des Benutzerprofil angebracht ist:

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) 

wie Mein Workflow-Modell (vereinfacht) aussieht: nicht

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) 

Obwohl die Lösung sein könnte ruhig einfach, wird mein Gehirn Sag mir.

Danke für Ihre Hilfe.

Antwort

66

Haben Sie so etwas wie dies versucht:

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

oder gerade wenn self.role.id ist keine Liste von pks:

module.workflow_set.filter(trigger_roles__id__exact=self.role.id, allowed=True) 
+1

das nicht scheinen zu arbeiten. Da die self.role.id nur ein int ist und die trigger_roles eine Liste von ihnen ist, würde ich ein invertiertes in, wie contains benötigen, aber wie ich herausgefunden habe, enthält contains nur für Strings. –

+5

Das zweite Beispiel * sollte * funktionieren. Wenn der Wert in 'self.role.id' eine der Auslöserrollen ist, sollte dieser Filter alle Workflows ziehen, bei denen eine der Auslöserrollen der Wert in' self.role.id' ist. Grundsätzlich verhält sich das genau wie eine "enthält" -Funktion. Es sei denn, wir verpassen alle etwas. –

+0

@Jordan Reiter: "contains" wird in sql in "like" umgewandelt was nicht das was der OP will und ich denke das er schon darauf hinweist, in der anderen Hand wird "exact" in "=" oder "is" umgewandelt was ist die Idee hier. – mouad

4

Singularität ist fast direkt mit dem ersten Beispiel. Sie müssen nur sicherstellen, dass es eine Liste ist. Das zweite Beispiel, das trigger_roles__id__exact überprüft, ist jedoch eine bessere Lösung.

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

Der einfachste Ansatz, dies zu erreichen für equalty über die gesamte Instanz (anstelle der id) in der ManyToManyField Überprüfung würde. Das sieht aus, wenn sich die Instanz in der Beziehung "Viele zu Viele" befindet. Beispiel:

3

Ich weiß, dass dies eine alte Frage ist, aber es sieht so aus, als hätte der OP nie ganz die Antwort bekommen, nach der er gesucht hat. Wenn Sie zwei Mengen von ManyToManyFields haben, die Sie vergleichen möchten, verwenden Sie den Operator __in, nicht contains. So zum Beispiel, wenn Sie ein „Ereignis“ Modell mit einem ManyToMany zu „Gruppe“ auf dem Feld haben eventgroups und Ihre User-Modell (natürlich) legt zur Gruppe, können Sie wie folgt abfragen:

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