For multi-select boxes where you have a list of things you want to filter on, and you want the queryset returned to be an OR’d set.
qset = Q(mode__exact=modes[0])
if len(modes) > 1:
for mode in modes[1:]:
qset = qset | Q(mode__exact=mode)
r = Responses.objects.filter(qset)
Now, I need to figure out how to do this as a list comprehension!
For extra coolness, you can see what SQL you’re generating:
print r.query.as_sql()
9 Responses
Travis Cline
August 13th, 2009 at 9:33 pm
1A slight golfing:
qset = Q()
for mode in modes:
qset |= Q(mode=mode)
r = Responses.objects.filter(qset)
or:
r = Responses.objects.filter(reduce(lambda x,y: x|Q(mode=y), modes, Q()))
But that’s probably getting too clever.
Ryan
August 14th, 2009 at 2:28 am
2You could start off with qset = Q(), and then loop through all the modes, OR’ing them together, without having to check the length.
Bartek
August 14th, 2009 at 7:14 am
3To make it a list comprehension you can try something like this:
import operator
qset = reduce(operator.__or__, [Q(mode__exact=mode) for mode in modes[1:]])
Didn’t test it, but it should work. Perhaps it can even be improved
Andre LeBlanc
August 14th, 2009 at 8:10 am
4I’m about 90% sure that
qset = Responses.objects.filter(mode__in=modes)
would have the exact same effect.
also, naming a model after the plural form of the word is considered bad form. the model really should be called “Response” but thats just nitpicking.
Brian Luft
August 14th, 2009 at 9:15 am
5While OR’ing Q objects together can be useful in some scenarios (may not scale well), why didn’t you use something like:
Responses.objects.filter(mode__in=modes)
Elf Sternberg
August 14th, 2009 at 9:47 am
6Brian, that’s useful under most circumstances, but in actual usage, I was getting querysets generated from multiple, sometimes remote, sources, and needed them OR’d together for the final result. The snippet I posted was simply for illustrative purposes.
Elf Sternberg
August 14th, 2009 at 9:49 am
7Andre, yes, I know about the plural vs. singular. It’s correct in the production code; I slipped making the example. And as I pointed out to Brian, in the production code multiple remote applications are being sent requests for querysets that need to be OR’d for the final production. Would it work correctly for, say, “contains” as the argument? (There’s a lot of text string searching going on.)
fayce
November 7th, 2009 at 12:41 pm
8Thank you for this post ! all thoses answers were helpful to me and really instructive… but I still can find how I can apply it to my problem even if it’s really similar.
Everything is dynamic in my queryset:
- the logical operator ( | or &)
- the operator (lte, gte, icontains ….)
- the name of the field (what you call the mode?)
- and the value…
I would like to build the complete queryset from strings, like this:
tab =
[['field1','value1','operator1','logical-operator1'],
['field2','value2','operator2','logical-operator2'],
['field3','value3','operator3','logical-operator3']
]
for e in tab:
req = req e[3] Q(e[0]__e[2]=e[1])
r = Obj.Objects.filter(req)
I know this is completely wrong and will never work.. but this is the idea..
Thank you for you help !
fayce
November 7th, 2009 at 3:54 pm
9I found the solution ! and it works !!
I had to combine Travis Cline method and some dicts and everything works just fine…
So, if someone is interested to know more about how I did, feel free to ask.
RSS feed for comments on this post · TrackBack URI
Leave a reply
Categories
Archives
Links
Meta
Calendar
Recent Entries
Recent Comments
Most Commented
Elf Sternberg is proudly powered by WordPress - BloggingPro theme by: Design Disease