fast-pager
Turn your Pydantic models into filterable, sortable, paginated FastAPI query parameters — automatically.
fast-pager reads the Pydantic models you already use in your FastAPI routes and
generates type-safe query parameters for filtering, sorting and pagination.
Those parameters show up in your OpenAPI docs for free, and compile down to a
real database query (MongoDB first, more backends later).
class User(BaseModel):
name: str
age: int
@app.get("/users")
async def list_users(q: FilterQuery[User] = FilterDepends(User)):
return await db.users.find(q.to_mongo()).to_list(None)
A request to:
GET /users?name__contains=ana&age__gte=21&age__lt=65&sort=-age&limit=20
…compiles to:
{"name": {"$regex": "ana"}, "age": {"$gte": 21, "$lt": 65}}
# sort=[("age", -1)], skip=0, limit=20
# (values in `contains` filters are regex-escaped before compilation)
…and every one of those parameters is documented, validated and typed in /docs.
Want the classic "items + total" response? Page[T] and paginate() are
the one-line opt-in — correct OpenAPI schema included, works with motor and
pymongo alike (duck-typed, no driver dependency):
@app.get("/users", response_model=Page[User])
async def list_users(q: FilterQuery[User] = FilterDepends(User)):
return await q.paginate(db.users) # {"items": [...], "total": 137, "limit": 20, "offset": 0}
Need a curated public surface? Declare an allow-list FilterSet — anything
not listed is not filterable — and the call site doesn't change:
class UserFilter(FilterSet):
class Meta:
model = User
fields = {"name": ["contains"], "age": ["gte", "lte"]}
@app.get("/users")
async def list_users(q: FilterQuery[User] = FilterDepends(UserFilter)): ...
Running on SQL instead of Mongo? The same q compiles to SQLAlchemy 2.0
(pip install 'fast-pager[sqlalchemy]') — only the backend swaps:
@app.get("/users")
def list_users(q: FilterQuery[User] = FilterDepends(User)):
stmt = q.apply_sqlalchemy(select(UserRow)) # WHERE + ORDER BY + LIMIT/OFFSET
return session.execute(stmt).scalars().all()
Built with AI
This project is designed and developed with the assistance of AI (Anthropic's Claude Code). Design documents and code are AI-generated and human-reviewed.
Status
fast-pager is under active development. Everything shown above is
shipped: the zero-config filtering pipeline over the full type surface
(scalars, arrays, nested models, elem element-matching, gated maps), the
Mongo compiler, per-field Filterable(...) control, allow-list
FilterSets, and the Page[T]/paginate() response envelope. The project
is still pre-1.0: per SemVer, breaking changes bump the minor version and
are called out in release notes. See the
changelog for exactly
what each version shipped.
Documentation
The full documentation site — getting started, tutorials, operator
reference, and the design documents below — lives at
fast-pager.eytanohana.com.
It's built with Zensical from docs/; see
docs/contributing/docs-site.md for how
it's configured and how to preview it locally.
Contributing
Dev setup, quality gates, and conventions live in
CONTRIBUTING.md. The short version: uv sync --all-groups,
make ruff + mypy + pytest happy (CI enforces all three plus a coverage floor
and an oldest-supported-dependencies job), and keep commits small.
Releasing (maintainers)
Releases are fully automated. From a clean main:
./scripts/release.sh patch # or minor / major
The script bumps the version in pyproject.toml (via uv version --bump),
commits, tags v<version>, and pushes. The tag triggers
release.yml, which:
- verifies the tag matches the
pyproject.tomlversion, - runs the full CI matrix,
- builds with
uv buildand publishes to PyPI via Trusted Publishing (OIDC — no API tokens), - creates the GitHub Release with generated notes.
fast_pager.__version__ reads from package metadata, so the version lives in
exactly one place.
Design documents
These are the product-design documents the implementation is built from. Read them in order:
| # | Document | What it covers |
|---|---|---|
| 00 | Overview & Vision | The problem, goals, non-goals, naming, guiding principles |
| 01 | Developer Experience | API surface options explored, the recommended ergonomics |
| 02 | Type & Operator System | Which Python types we support, their operators, compound types, per-field configurability |
| 03 | Architecture | The layered pipeline, the filter AST, the FastAPI signature trick |
| 04 | Backend Roadmap | Mongo today, generalizing to any database tomorrow |
| 05 | Roadmap & Release Plan | Phased path to a clean 1.0 on PyPI |
Start with 00-overview.md.
Release files for fast-pager 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fast_pager-0.4.0.tar.gz | 49.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fast_pager-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 111.0 kB
Release files / fast_pager-0.4.0.tar.gz
| Download URL | fast_pager-0.4.0.tar.gz |
|---|---|
| Size | 49.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dab3cdd868a75ebb63bfe9f71080c204253080294cf8bd6a51307a0e00b067c6
|
|
BLAKE2b-256 checksum How to use checksums |
4fd42d56a7b3789df83d6c0453ba11b5cf7a29e4affe840217d82b34517dfb11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fast_pager-0.4.0-py3-none-any.whl
| Download URL | fast_pager-0.4.0-py3-none-any.whl |
|---|---|
| Size | 61.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
283ed426f0c107b05757e9537066a2ef8ef190657555b18cc643cdd74ea203c6
|
|
BLAKE2b-256 checksum How to use checksums |
c3e283255ac5c06bb4a07c3808b07a403f63c2e625f490e76bfa60ad020a17dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|