How can I add OR conditions in Django filters but with conditions

52 Views Asked by At

So let's say I have a interface that has a filters section (not django filters but just normal filters that we see on product listings etc). Like this

Now what I want is that: If Individual is checked, then only show Individual which is very easy.

But things get messy when you choose two, let's say individuals and couples. Then I would need alot of if statements for this and changing the filters accordingly.

I'm doing this currently like this:

if individual and not couple and family:
                query = query.filter(Q(partner="individual") | Q(partner="family"))

            if individual and couple and not family:
                query = query.filter(Q(partner="individual") | Q(partner="couple"))

            if not individual and couple and family:
                query = query.filter(Q(partner="family") | Q(partner="couple"))

            if individual and not couple and not family:
                query = query.filter(partner="individual")

            if not individual and couple and not family:
                query = query.filter(partner="couple")

            if not individual and not couple and family:
                query = query.filter(partner="family")

which is very messy.

Basically I need something like this (PHP Code).

$sql = "SELECT * FROM abc WHERE";
if($individual){
   $sql .= " partner=individual"; 
}
if($couple){
   $sql .= " OR partner=couple"; 
}
if($family){
   $sql .= " OR partner=family"; 
}
$sql .= " order by id desc";

now I know the php part above is not correct, it will through error if $individual is false because then there would not be any condition after WHERE and directly OR. But it's just to give you an idea.

Thanks!

2

There are 2 best solutions below

0
Razenstein On BEST ANSWER

You could create a list of activated options and use __in lookup, like so:

my_list=(opt1, opt3)
query_filtered=query.filter(partner__in=my_list)
0
nigel222 On

You can compound Q objects programmaticaly before using them in a filter. | is just a Python operator. So if you can obtain a list of the buttons:

# button_list (for example) ['individual', 'family' ]

q = Q( partner="*impossible*" )
for selected in button_list:
     q = q | Q( partner = selected)

query = query.filter( q)

Obviously this depends on the values in button_list being the values of partnet that you want to filter on. If you have selectable oprions which don't all relate to filtering on the same field, or different strings, you can instead use a lookup in a hash

filters = {
    'individual': Q( partner = 'individual'),
    'awkward':     Q( special_policy = True),
    ...
}
...

for selected in button_list:
    q = q | filters[ selected]   

This will crash if selected is not a valid key. You might prefer

for selected in button_list:
    filter = filters.get( selected, None)
    if filter:
        q = q | filter
    else:
        # log the fact that you've got "{selected}"
        # which isn't a defined filter
        pass