0

I have a Q object like this.

params = Q(salt_spray__iregex=keyword) | Q(special_function__iregex=keyword) | Q(comment__iregex=keyword)

Here When I filter my model on the basis of this, things work fine.

Model.objects.filter(params)

But I want to do the following.

params = Q(salt_spray__iregex=keyword) | Q(special_function__iregex=keyword) | Q(comment__iregex=keyword)
if data.get('market'):
    params[project__market] = data['market'] # not sure about this step. 
Model.objects.filter(params)

Code after Solution

data = self.cleaned_data

keyword = data['keyword']
params = Q()
if keyword:
    params |= Q(salt_spray__iregex=keyword) | Q(special_function__iregex=keyword) | Q(comment__iregex=keyword) # Note OR Operator. 

if data['market']:
    params &= Q(project__market=data['market']) # Note here AND Operator 
innovations = Innovation.objects.filter(params)
return innovations
Tomasz Jakub Rup
  • 9,464
  • 7
  • 44
  • 47
A.J.
  • 6,664
  • 10
  • 55
  • 74

2 Answers2

1

You need to or the Q objects with the | operator:

params = Q(salt_spray__iregex=keyword) | Q(special_function__iregex=keyword) | Q(comment__iregex=keyword)
if data.get('market'):
    params |= Q(project__market=data['market'])
Model.objects.filter(params)

Or use operator.or_ as @rinti has mentioned.

Maciej Gol
  • 13,758
  • 4
  • 31
  • 49
  • Excellent solution. You can combine AND or OR operators accordingly. – A.J. Jul 17 '14 at 10:05
  • @Jack, be aware when combining both _AND_ and _OR_ operators. If you want to _AND_ 2 groups of queries, you need to do `&= – Maciej Gol Jul 17 '14 at 10:08
  • Do you mean `&= – A.J. Jul 17 '14 at 10:13
  • @Jack, sorry, I've missed the closing `>` - it should be `&= `. – Maciej Gol Jul 17 '14 at 10:13
  • Perfect, Can you see my Updated code above and see its correct? – A.J. Jul 17 '14 at 10:20
  • @Jack, I think it should be fine. It's equivalent to `(salt_spray | special_function) & project__market`. It could get messy if you did _OR_ something later on, e.g. _OR_ ing `Q1` and `Q2` would give `(((salt_spray | special_function) & project__market) | Q1) | Q2)` – Maciej Gol Jul 17 '14 at 10:23
  • Great, If i need to do more ORs and ANDs I will try to simplify it. – A.J. Jul 17 '14 at 10:35
  • @Jack, just remember that `Q1 &= Q2` is equivalent to `Q1 = Q1 & Q2` which is equivalent to `(conditions for Q1) & (conditions for Q2)`. Same for `|`. If you need to add a group of conditions with the same operator using a different operator, remember to first create a `Q` object that encapsulates the group with given operator, then `&=` or `|=` it with the rest of the filters. – Maciej Gol Jul 17 '14 at 10:38
0

import operator then you can do it like this:

params = []

# Add as much as you like to your list dynamically
params.append(Q(something))

Model.objects.filter(reduce(operator.or_, params))
rinti
  • 1,243
  • 1
  • 12
  • 16