How to add an OR criterion to an existing QuerySet?

133 views
Skip to first unread message

Bernd Wechner

unread,
Mar 14, 2018, 11:45:41 PM3/14/18
to Django users
Another interesting problem.

Let's say I have a QuerySet which already applies some filters. It's provided by a third party library mind you, and all you have is the QuerySet instance.

Now I would like to loosen the filter a bit, ad an ORed filter. Not a trivial thing it seems. Q objects aren't obviously available unless we can extract the Q object for the existing filter.

In code the scenario looks like:

# A Queryset is buillt with some unknown filter criteria
qs
= Model.objects.filter(....)
# All we see in out code is the QuerySet qs. But we want somehow to add a filter criterion. We can do this:
qs
= qs.filter(...)
# and the new filter criteria will be added, but with AND logic. What if we want to add one with OR logic (loosen the filter some)
# It might look like:
qs
= qs | Q(...)
# But does it? How can we add an ORed filter criterion to qs?

Basically, there's a chance it's not possible! But if it is, it would rely on some syntax for combining chained .filter() methods with an OR logic (which seems constrained to Q objects) or extracting the current filter from a QuerySet and its constraints as a Q object, so we can OR a new constraint to it, and then reapply the filter.

Bit of a mystery to me.

Hoping someone has some insights I'm not getting from the docs here.

Regards,

Bernd.




Simon Charette

unread,
Mar 15, 2018, 12:49:17 AM3/15/18
to Django users
Hello Bern,

You're actually pretty close to the solution.

You should be able to OR an existing querysets filters by using the "|" operator
between querysets of the same model. That would be the following:

qs |= Model.objects.filter(Q(...))

Simon

Bernd Wechner

unread,
Mar 15, 2018, 2:32:18 AM3/15/18
to django...@googlegroups.com, Simon Charette
Simon,

Thanks enormously. A little experimentation and I got that to work! Brilliant. Am most pleased it was possible. Good ol' Django to the rescue.

The thing I got stuck on for a bit was an assertion failure because qs was DISTINCT and the or'ed qs was not (the or operation raises a rather cryptic assertion failure then ;-). But nailed it, by examing the SQL and yes, one contained a DISTINCT clause so I just added it to the other and was happy ...

Regards,

Bernd.

Simon Charette wrote:
--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/2BuFFMDL0VI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/d9d845e5-62c2-479c-83cc-6d21b719a74f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Simon Charette

unread,
Mar 15, 2018, 10:39:01 AM3/15/18
to Django users
Bernd,

Glad you managed to achieve what you were after!

Combination of querysets is definitely an obscure part or the ORM API.

I couldn't even find a single mention of it in the documentation even if
I know it's supported.

It might be worth opening a ticket about it if you can't find any mention
of it yourself.

Best,
Simon
Reply all
Reply to author
Forward
0 new messages