Socket
Book a DemoInstallSign in
Socket

fastapi-fsp

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastapi-fsp

Filter, Sort, and Paginate (FSP) utilities for FastAPI + SQLModel

pipPyPI
Version
0.1.1
Maintainers
1

fastapi-fsp

Filter, Sort, and Paginate (FSP) utilities for FastAPI + SQLModel.

fastapi-fsp helps you build standardized list endpoints that support:

  • Filtering on arbitrary fields with rich operators (eq, ne, lt, lte, gt, gte, in, between, like/ilike, null checks, contains/starts_with/ends_with)
  • Sorting by field (asc/desc)
  • Pagination with page/per_page and convenient HATEOAS links

It is framework-friendly: you declare it as a FastAPI dependency and feed it a SQLModel/SQLAlchemy Select query and a Session.

Installation

Using uv (recommended):

# create & activate virtual env with uv
uv venv
. .venv/bin/activate

# add runtime dependency
uv add fastapi-fsp

Using pip:

pip install fastapi-fsp

Quick start

Below is a minimal example using FastAPI and SQLModel.

from typing import Optional
from fastapi import Depends, FastAPI
from sqlmodel import Field, SQLModel, Session, create_engine, select

from fastapi_fsp.fsp import FSPManager
from fastapi_fsp.models import PaginatedResponse

class HeroBase(SQLModel):
    name: str = Field(index=True)
    secret_name: str
    age: Optional[int] = Field(default=None, index=True)

class Hero(HeroBase, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)

class HeroPublic(HeroBase):
    id: int

engine = create_engine("sqlite:///database.db", connect_args={"check_same_thread": False})
SQLModel.metadata.create_all(engine)

app = FastAPI()

def get_session():
    with Session(engine) as session:
        yield session

@app.get("/heroes/", response_model=PaginatedResponse[HeroPublic])
def read_heroes(*, session: Session = Depends(get_session), fsp: FSPManager = Depends(FSPManager)):
    query = select(Hero)
    return fsp.generate_response(query, session)

Run the app and query:

  • Pagination: GET /heroes/?page=1&per_page=10
  • Sorting: GET /heroes/?sort_by=name&order=asc
  • Filtering: GET /heroes/?field=age&operator=gte&value=21

The response includes data, meta (pagination, filters, sorting), and links (self, first, next, prev, last).

Query parameters

Pagination:

  • page: integer (>=1), default 1
  • per_page: integer (1..100), default 10

Sorting:

  • sort_by: the field name, e.g., name
  • order: asc or desc

Filtering (repeatable sets; arrays are supported by sending multiple parameters):

  • field: the field/column name, e.g., name
  • operator: one of
    • eq, ne
    • lt, lte, gt, gte
    • in, not_in (comma-separated values)
    • between (two comma-separated values)
    • like, not_like
    • ilike, not_ilike (if backend supports ILIKE)
    • is_null, is_not_null
    • contains, starts_with, ends_with (translated to LIKE patterns)
  • value: raw string value (or list-like comma-separated depending on operator)

Examples:

  • ?field=name&operator=eq&value=Deadpond
  • ?field=age&operator=between&value=18,30
  • ?field=name&operator=in&value=Deadpond,Rusty-Man
  • ?field=name&operator=contains&value=man

You can chain multiple filters by repeating the triplet:

?field=age&operator=gte&value=18&field=name&operator=ilike&value=rust

Response model

{
  "data": [ ... ],
  "meta": {
    "pagination": {
      "total_items": 42,
      "per_page": 10,
      "current_page": 1,
      "total_pages": 5
    },
    "filters": [
      {"field": "name", "operator": "eq", "value": "Deadpond"}
    ],
    "sort": {"sort_by": "name", "order": "asc"}
  },
  "links": {
    "self": "/heroes/?page=1&per_page=10",
    "first": "/heroes/?page=1&per_page=10",
    "next": "/heroes/?page=2&per_page=10",
    "prev": null,
    "last": "/heroes/?page=5&per_page=10"
  }
}

Development

This project uses uv as the package manager.

  • Create env and sync deps:
uv venv
. .venv/bin/activate
uv sync --dev
  • Run lint and format checks:
uv run ruff check .
uv run ruff format --check .
  • Run tests:
uv run pytest -q
  • Build the package:
uv build

CI/CD and Releases

GitHub Actions workflows are included:

  • CI (lint + tests) runs on pushes and PRs.
  • Release: pushing a tag matching v*.*.* runs tests, builds, and publishes to PyPI using PYPI_API_TOKEN secret.

To release:

  • Update the version in pyproject.toml.
  • Push a tag, e.g. git tag v0.1.1 && git push origin v0.1.1.
  • Ensure the repository has PYPI_API_TOKEN secret set (an API token from PyPI).

License

MIT License. See LICENSE.

Keywords

api

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts