5

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)))

4 Answers 4

8

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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,

Comments

0

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.

2 Comments

Yeah.. it's your opinion.. but it's not more repetitive. Python programmer always has to look for simple and clean solution.
A line of python code longer than 80 characters is always unreadable. It is my opinion after 20 years.
0

I would use

objects = MyObject.objects.filter(x=alpha)
if beta:
    # Additional filter because of ...
    objects = objects.filter(y=beta)

Your way is simply harder to read. Python should be easy to read. Note that this only works right for simple filters (no multi-valued relations), as buffer mentions. Otherwise, your original query looks best to me.

2 Comments

Careful with this. For multi-valued relations Everything inside a single filter() call is applied simultaneously to filter out items matching all those requirements. Successive filter() calls further restrict the set of objects, but for multi-valued relations, they apply to any object linked to the primary model, not necessarily those objects that were selected by an earlier filter() call.
Thanks, I didn't actually know the details of that. Updated answer a bit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.