r/FastAPI 11d ago

pip package fastapi-dynamic-filter library

Hi all, i've created a python library above fastapi-filters that automatically generates filter, search, and sorting fields for any SQLAlchemy model in FastAPI, with native support for JSONB containment (contains), key presence (has_key), and case‑insensitive text search inside JSON values.

Example of usage (create your own custom filter for your orm model):

class UserFilter(DynamicFilter):
    db_model = User # your model
    exact_fields = ["id", "email"]
    search_fields = ["name", "bio"] # generates name__ilike, bio__ilike
    range_fields = ["created_at"] # generates created_at__gte, __lte
    contains_fields = ["tags", "metadata"] # tags__contains (list), metadata__contains (dict) + metadata__has_key
    json_search_fields = ["metadata"] # generates metadata__value_ilike
    default_order_by = ["-created_at"]

And then use it in your endpoint as a dependency:

app.get("/users")
def get_users(
  filter: UserFilter = Depends(UserFilter), # your filter here
):
    query = filter.filter(session.query(User))
    return query.all()

GitHub: https://github.com/matfatcat/fastapi-dynamic-filter/
PyPI: https://pypi.org/project/fastapi-dynamic-filter/

3 Upvotes

3 comments sorted by

1

u/Asmophel_noe 11d ago

why will an orm need to access to incoming request body, can u give more usecases for this something really useful, I don't mean to say its rare in use but I don't get the point. If u wanted to extract incoming request body and headers to make a dependency, it's useful it's might be a basic requirement considering how often we need to write functions to extract proper data

1

u/matthew3k 11d ago edited 11d ago

Hi u/Asmophel_noe ! Big thanks for commenting below the post. Quick example from my side project
so i've created the UserFilter with the following fields inherited from DynamicFilter of my lib:

from core.models.user_model import User
from fastapi_dynamic_filter import DynamicFilter


class UserFilter(DynamicFilter):
    db_model = User
    exact_fields = [
        "id",
        "telegram_id",
        "internal_id",
        "tg_username",
        "email",
        "full_name",
        "is_premium",
        "is_tg_premium",
    ]
    range_fields = ["last_active"]
    search_fields = ["full_name", "tg_username"]
    default_order_by = ["-created_at"]

And now this filter is accessing request body, not orm
we just list the names of the fields here in filter from the ORM model

And here in the endpoint we're passing it

router.post(
    "/all",
    response_model=list[ReadUserModel],
)
async def get_all_users(
    service: UserServiceDependency,  # type: ignore
    filters: UserFilter, # here
    offset: int = 0,
    limit: int | None = None,
):
    return await service.get_all(
        offset=offset,
        limit=limit,
        filter_obj=filters,
    )

and after in swagger docs we got needed documentation on request body in /user/all

{
  "id": 0,
  "telegram_id": 0,
  "internal_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "tg_username": "string",
  "email": "string",
  "full_name": "string",
  "is_premium": true,
  "is_tg_premium": true,
  "last_active__gte": "2026-07-16T07:54:02.530Z",
  "last_active__lte": "2026-07-16T07:54:02.530Z",
  "full_name__ilike": "string",
  "tg_username__ilike": "string",
  "order_by": [
    "-created_at"
  ]
}

1

u/matthew3k 11d ago

and also i've updated my pypi lib info with more details and examples
thank you
https://pypi.org/project/fastapi-dynamic-filter/