Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django query with variable number of filter arguments

I have a Django query that fetches from MyModel based on certain conditions:

if beta:
    MyModel.object.filter(x=alpha, y=beta)
else:
    MyModel.object.filter(x=alpha)

Is it possible to eliminate the if beta: check and do it in a single line i.e. make the query filter on y only when beta is not None

Is this a good (Djangonic) way:

MyModel.object.filter(**{'x':alpha, 'b':beta} if beta else **{'x':alpha})

Or is it possible to do something like this (I know the following is wrong, but can it be fixed to give the correct meaning?):

MyModel.object.filter(Q('x'=alpha) & (beta && Q('y'=beta)))
like image 436
user Avatar asked May 20 '14 07:05

user


3 Answers

In such situations I'm using solution like below:

filter_kwargs = {'x': alpha}
if beta:
    filter_kwargs['y'] = beta

 MyModel.objects.filter(**filter_kwargs)

It is easy to expand when new conditions come in into the project requirements, but unfortunately its not a one-liner solution.

like image 195
Kamil Rykowski Avatar answered Nov 19 '22 17:11

Kamil Rykowski


In my opinion it isn't good solution. I have problem to read and understand the code.

You can also do something like this:

objects_ = MyModel.objects.filter(x=alpha, y=beta) if beta else MyModel.objects.filter(x=alpha)

return objects_

For me it's more clean.. but it's only my opinion.

like image 35
Sławek Kabik Avatar answered Nov 19 '22 16:11

Sławek Kabik


One way to do this is to use Q objects, see this answer.

In your case :

query = Q(x=alpha)
if beta:
    query = query & Q(y=beta)
MyModel.object.filter(query)

Not shorter than other examples, but it could be cleaner if you were to add more variables to test.

HTH,

like image 1
Ambroise Avatar answered Nov 19 '22 17:11

Ambroise