Metadata-Version: 2.4
Name: fastapi-smart-paginator
Version: 0.1.1
Summary: Lightweight, zero-config pagination, filtering, and sorting for FastAPI + SQLAlchemy
Project-URL: Homepage, https://github.com/anjanip/fastapi-smart-paginator
Project-URL: Repository, https://github.com/anjanip/fastapi-smart-paginator
Project-URL: Issues, https://github.com/anjanip/fastapi-smart-paginator/issues
Project-URL: Changelog, https://github.com/anjanip/fastapi-smart-paginator/blob/main/CHANGELOG.md
Author: Anjani Pandey
License-Expression: MIT
License-File: LICENSE
Keywords: fastapi,filtering,pagination,sorting,sqlalchemy
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: pydantic>=2.0
Requires-Dist: sqlalchemy>=1.4
Provides-Extra: dev
Requires-Dist: fastapi>=0.100.0; extra == 'dev'
Requires-Dist: httpx>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# fastapi-smart-paginator

[![PyPI version](https://img.shields.io/pypi/v/fastapi-smart-paginator)](https://pypi.org/project/fastapi-smart-paginator/)
[![Python](https://img.shields.io/pypi/pyversions/fastapi-smart-paginator)](https://pypi.org/project/fastapi-smart-paginator/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**Lightweight, zero-config pagination, filtering, and sorting for FastAPI + SQLAlchemy.**

Unlike heavyweight alternatives, `fastapi-smart-paginator` works directly with raw SQLAlchemy queries — no magic, no hidden complexity. Just add 3 lines to any endpoint.

## Features

- 📄 **Pagination** — Automatic PK ordering, input validation, size capping
- 🔍 **Filtering** — 6 comparison operators (`eq`, `ne`, `gt`, `gte`, `lt`, `lte`)
- ↕️ **Sorting** — Ascending/descending with field validation
- 📦 **Pydantic Response Model** — `PaginatedResponse` for auto-generated OpenAPI docs
- ✅ **Type-safe** — Full type hints with `py.typed` marker

## Installation

```bash
pip install fastapi-smart-paginator
```

## Quick Start

```python
from fastapi import FastAPI, Depends, Query
from sqlalchemy.orm import Session

from fastapi_smart_paginator import paginate, apply_filters, apply_sorting, PaginatedResponse

app = FastAPI()

@app.get("/users", response_model=PaginatedResponse)
def list_users(
    page: int = Query(1, ge=1),
    size: int = Query(10, ge=1, le=100),
    sort_by: str | None = None,
    order: str = "asc",
    age__gte: int | None = None,
    db: Session = Depends(get_db),
):
    query = db.query(User)

    # Filter
    filters = {}
    if age__gte is not None:
        filters["age__gte"] = age__gte
    query = apply_filters(query, User, filters)

    # Sort
    query = apply_sorting(query, User, sort_by=sort_by, order=order)

    # Paginate
    return paginate(query, page=page, size=size)
```

## Example Response

```json
{
  "total": 150,
  "page": 2,
  "size": 10,
  "pages": 15,
  "data": [
    {"id": 11, "name": "User 011", "email": "user11@example.com", "age": 31},
    {"id": 12, "name": "User 012", "email": "user12@example.com", "age": 32}
  ]
}
```

## API Reference

### `paginate(query, page=1, size=10, order_by=None)`

Paginate a SQLAlchemy query.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `query` | `Query` | required | SQLAlchemy query |
| `page` | `int` | `1` | Page number (1-based, clamped to ≥1) |
| `size` | `int` | `10` | Items per page (clamped to 1–100) |
| `order_by` | `ColumnElement \| None` | `None` | Custom ordering (auto PK if None) |

Returns: `PaginatedResponse`

### `apply_filters(query, model, filters)`

Apply dynamic filters using `field__operator` syntax.

```python
apply_filters(query, User, {"age": 25})          # age == 25
apply_filters(query, User, {"age__gte": 18})     # age >= 18
apply_filters(query, User, {"age__lt": 65})      # age < 65
apply_filters(query, User, {"name__ne": "admin"})# name != "admin"
```

Supported operators: `eq` (default), `ne`, `gt`, `gte`, `lt`, `lte`

### `apply_sorting(query, model, sort_by=None, order="asc")`

Apply sorting to a query. Raises `ValueError` for invalid `order` values.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sort_by` | `str \| None` | `None` | Column name |
| `order` | `str` | `"asc"` | `"asc"` or `"desc"` (case-insensitive) |

### `PaginatedResponse`

Pydantic model for type-safe responses with auto OpenAPI schema.

## Roadmap

- [ ] `created_at` default ordering option
- [ ] Cursor-based pagination
- [ ] Advanced filters (`in`, `like`, `between`)
- [ ] Async SQLAlchemy support
- [ ] Response serializer hooks

## License

MIT
