question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Chaining separate .where() clauses with OR instead of AND

See original GitHub issue

I have an existing query in my code that I wish to further extend the query with additional WHERE criteria, but chained with OR instead of AND.

I can’t find a way to do this in peewee. Am I missing something? I am aware that I can dynamically chain multiple clauses with OR using reduce(operator.or_, clauses), but this is a different thing – it doesn’t help me to extend an additional query.

I believe I can achieve this with something like query._where = query._where | additional_criteria, but this feels like a hack that requires knowledge of peewee’s implementation details, not the published API – always a bad idea.

I’m currently tinkering with a helper function something like the following:

def orwhere(query, *expressions):
    import operator
    query = query.clone()
    reduced = reduce(operator.and_, expressions)
    query._where = (query._where or True) | reduced  # `or True` so that if it's the first expression in the clause, it still behaves consistently by broadening the queryset rather than restricting it.
    return query

What do you think about adding .orwhere() to the query API? Or is there a better way that I’m missing?

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

10reactions
askabelincommented, Feb 16, 2017

Sorry for necroposting but I have exactly the same issue. Actually this problem is not related with peewee. E.g. django ORM has the same API. If you want to extend your query you need to work with expression instead of query:

expression = (Model.a == 'x') & (Model.b == 'y')
if something:
    expression |= (Model.c == 'z')

result = Model.select().where(expression)
5reactions
coleifercommented, Feb 27, 2019

The best way is to:

import operator
from functools import reduce

expr_list = [
    (Foo.bar == 1),
    (Foo.baz == 2),
    (Foo.biz == 4)]

orexpr = reduce(operator.or_, expr_list)

You can use operator.and_ to AND- them together.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Linq chaining where clauses as an Or instead of And [duplicate]
I need to change the logic for the last where clause in the below code snippet to behave as an "OR" instead of...
Read more >
SQL WITH: Organize Complex Queries
The WITH clause adds named subqueries to SQL queries. ... They are not stored in the database schema: instead, they are only valid...
Read more >
Replace Nested Conditional with Guard Clauses
Solution. Isolate all special checks and edge cases into separate clauses and place them before the main checks. Ideally, you should have a...
Read more >
WITH — Snowflake Documentation
WITH¶. The WITH clause is an optional clause that precedes the body of the SELECT statement, and defines one or more CTEs (common...
Read more >
with - JavaScript | MDN - MDN Web Docs
The with statement extends the scope chain for a statement. ... you won't get an error — instead you'll just get unexpected results....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found