2012-04-05 5 views
0

Ich habe ein Formular, das eine Gruppe von 13 Kontrollkästchen hat, die zusammen meine Suchkriterien bilden ... außer dass ich auch ein Paar Radio-Buttons für ALLE oder IRGENDEINE hinzugefügt .Auf der Suche nach Django any() und all() auf Querysets

Ich hatte gehofft, weg elegant wie mit etwas zu bekommen:

priority_ids = request.GET.getlist("priority") # checkboxes 
collection = request.GET.get("collection") # radio buttons 
priorities = [] 
for priority_id in priority_ids: 
    priorities.append(Q(focus__priority=priority_id)) 
if (collection == "any"): qset = any(priorities) 
elif (collection == "all"): qset = all(priorities) 

jedoch jede() und alle() gibt einen boolean, kein queryset, die ich in einem Filter verwenden können. Ich will eine "any" oder "all", die das Äquivalent bedeutet "Q (...) | Q (...) | Q (...)" oder „Q (...) & Q (.. .) & Q (...) "für 1 bis 13 Kriterien.

Antwort

1

Es gibt nichts, was Django tun muss. Sie müssen nur Ihre Q -s mit & bzw. | in einer einfachen Schleife oder in einer kompakteren Weise mit reduce kombinieren.

Und in Bezug auf die Terminologie scheint es mir, dass Sie Q ein Queryset aufrufen, aber es ist nicht. Es ist ein Filter für ein Abfrage-Set. So etwas wie die folgenden funktionieren sollte:

priority_ids = request.GET.getlist("priority") 
collection = request.GET.get("collection") 
priority_filters = [] 
for priority_id in priority_ids: 
    priority_filters.append(Q(focus__priority=priority_id)) 

base_qs = SomeModel.objects.all() 

if collection == "any": 
    filtered_qset = base_qs.filter(reduce(operator.or_, priority_filters)) 
elif collection == "all": 
    filtered_qset = base_qs.filter(reduce(operator.and_, priority_filters)) 
+1

Beachten Sie, dass Ihre 'lambda's durch' operator.or_' und 'operator.and_' bzw. ersetzt werden. – Dougal

+0

+1, vielen Dank für das zeigen –

+0

Während wir bei ihm sind, könnte auch 'priority_filters = [Q (focus__priority = p_id) für p_id in priority_ids]' :) – Dougal