Skip to content

feat: server-side search, declarative ordering and advanced filters - #11

Merged
svalench merged 2 commits into
masterfrom
feat/search-ordering-filters
Sep 7, 2026
Merged

feat: server-side search, declarative ordering and advanced filters#11
svalench merged 2 commits into
masterfrom
feat/search-ordering-filters

Conversation

@svalench

@svalench svalench commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the last two Roadmap rows of the feature matrix (v1.5.0):

  • ?search= on LIST — server-side case-insensitive substring search across ListConfig.search_fields
  • Declarative ordering?ordering= validated against ListConfig.ordering_fields, - prefix for descending, declarative default ordering when omitted, 400 on unknown fields
  • Advanced filters?<field>= exact match plus ne/gt/gte/lt/lte/contains/in operators, restricted to the ListConfig.filters whitelist, values auto-coerced to int/float/bool

All built-in adapters supported: SQLAlchemy (sync & async), Tortoise ORM, Peewee — on both BaseViewset and AsyncBaseViewset.

Design: fully declarative via an inner ListConfig class on the Pydantic response schema (same pattern as RelatedConfig for eager loading). Without it, LIST behaves exactly as before — backward compatible, and custom adapters keep working because new kwargs are only forwarded when used.

Testing

  • 31 new tests in tests/test_search_ordering.py: config parsing helpers, sync/async viewsets end-to-end via TestClient, Tortoise/Peewee adapter behaviour
  • 294 tests total, coverage 88.5%, verified on Python 3.14.3
  • mkdocs build --strict passes

Docs

  • docs/pagination-filtering.md rewritten around ListConfig
  • Feature matrix: last two Roadmap rows → Supported (README + docs/index.md)
  • Roadmap and comparison tables updated

Alexander Valenchits added 2 commits September 7, 2026 04:43
- New ListConfig inner class on Pydantic schemas: search_fields,
  ordering_fields, ordering (default), filters (whitelist)
- ?search= does case-insensitive substring matching across search_fields
- ?ordering= validated against ordering_fields (- prefix for desc,
  400 on unknown fields, declarative default when omitted)
- Filter query params with eq/ne/gt/gte/lt/lte/contains/in operators,
  values coerced to int/float/bool, whitelist enforced
- Implemented in SQLAlchemy (sync+async), Tortoise and Peewee adapters
- utils/async_utils get_list_queryset accept the new arguments; new
  kwargs are only forwarded when used (custom adapters keep working)
- Fully backward compatible: no ListConfig -> unchanged behaviour
- 31 new tests (294 total, 88.5% coverage)
- Docs: pagination-filtering.md rewritten, feature matrix and roadmap
  updated (last two Roadmap rows are now Supported)
- Version bump to 1.5.0, release notes added
@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.90476% with 59 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
fastapi_viewsets/orm/peewee_adapter.py 2.70% 36 Missing ⚠️
fastapi_viewsets/orm/tortoise_adapter.py 4.54% 21 Missing ⚠️
fastapi_viewsets/orm/sqlalchemy_adapter.py 94.73% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@svalench
svalench merged commit 210aeb5 into master Sep 7, 2026
9 of 10 checks passed
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.

1 participant