Skip to content

fix: apply every chained exclude() call instead of only the last one - #1826

Open
moneebullah25 wants to merge 3 commits into
ormar-orm:masterfrom
moneebullah25:fix/chained-exclude-drops-earlier-1816
Open

moneebullah25 wants to merge 3 commits into
ormar-orm:masterfrom
moneebullah25:fix/chained-exclude-drops-earlier-1816

Conversation

@moneebullah25

Copy link
Copy Markdown

Fixes #1816

Problem

QuerySet.exclude() replaced the previously collected exclude clauses, so qs.exclude(a=1).exclude(b=2) only applied the last call and silently returned rows that should have been excluded (this also affects update() and delete() on such querysets).

Change

  • ormar/queryset/queryset.py: each exclude() call now appends its own group to exclude_clauses instead of replacing them. An argument-less exclude() is a no-op.
  • ormar/queryset/queries/filter_query.py: every exclude clause is negated individually and the results are ANDed, so chained calls compose as NOT a AND NOT b. A single exclude(a=1, b=2) call keeps its existing meaning.
  • tests/test_queries/test_chained_exclude.py: new tests for chained excludes, mixing with filter(), update()/delete(), empty exclude(), and or_/and_ groups with limit.

Checks run

  • ruff format --check and ruff check on the changed files: pass
  • mypy ormar tests --ignore-missing-imports: success
  • DATABASE_URL=sqlite:///test.db pytest --cov=ormar --cov=tests tests/: 669 passed, 25 skipped, 0 failed, 100% coverage
  • Added tests for the new behaviour
  • Docs not updated (no documented behaviour changed)
  • Not run against postgres/mysql backends (sqlite only)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chained exclude() calls silently drop all earlier excludes

1 participant