Reputation: 2198
I have a query which uses filter
but I know there is this thing called Q
but trying to play around with it, I am not sure how I can use Q
. I am not sure which one would be better but trying to know another way to do the query.
What I actually want to do is... for my queryset return I have a default field and two input fields which are options.
let's say, language in default is english, there is a location and title field. If location and title fields are available, make a query to query location, title, and language. If only location then only query location and language, if only title then only query title and language.
I have done it two ways, one with filter only which has less code...
postings = Posting.objects.filter(language='EN')
if kwargs.get('title'):
postings = postings.filter(title__icontains=kwargs.get('title'))
if kwargs.get('location'):
postings = postings.filter(location__icontains=kwargs.get('location'))
the above does work with using only filter
I am trying to see if I can do it with using Q
but cannot seem to make it work
I have something like this at the moment
if title and location:
postings = Posting.objects.filter(title__icontains=title, location__icontains=location, language='EN')
else:
queryQ = Q(posting_language='EN')
if title:
queryQ |= Q(title__icontains=title)
if location:
queryQ |= Q(location__icontains=location)
postings = Posting.objects.filter(queryQ)
can someone please give me a hand? Thanks in advance
Upvotes: 0
Views: 622
Reputation: 308779
Firstly, |
is for ORing Q
objects. You want &
for ANDing
them.
You could rewrite your filter code as:
queryQ = Q(posting_language='EN')
if title:
queryQ &= Q(title__icontains=title)
if location:
queryQ &= Q(location__icontains=location)
postings = Posting.objects.filter(queryQ)
However I don't see any real advantage of this. Personally I think your original code is more readable.
Upvotes: 4
Reputation: 697
I think you've misunderstood what Q is for. Q is mostly used in django for more complex query statements that require OR/AND.
So, you could do something like this:
postings = Posting.objects.filter(Q(title__icontain=title) | Q(location=location))
This will give you all the postings where title contains the title OR the location contains the location. It's not very useful in this context because icontains will fail with a Null value and return everything for an empty string value.
Q would be very useful if you needed postings for titles that used two different icontains
postings = Posting.objects.filter(Q(title__icontains=search_term_a) & Q(title__icontains=search_term_b))
Upvotes: 0