Supported Backends
mainfastapi_filter provides support for the following database backends:
- SQLAlchemy
- MongoEngine
- Beanie
repository·main·Indexed 43 days ago
https://github.com/arthurio/fastapi-filterA library for simplifying filtering and ordering of query parameters in FastAPI applications. Version 3.0.0 supports SQLAlchemy, MongoEngine, and Beanie backends. It provides FilterDepends for Swagger UI compatibility and error handling, the with_prefix utility for related model filtering, and built-in support for search and order_by configurations.
fastapi_filter provides support for the following database backends:
You can filter on related models by nesting filter classes and using the with_prefix utility.
To make this work in your database query, you must ensure your query performs a join (e.g., .outerjoin()) with the related model.
with_prefix(prefix, filter_class) creates a new filter instance where all fields from the filter_class are prefixed with the provided prefix. This allows you to use query parameters like ?prefix__field=value.
from typing import Optional
class AddressFilter(Filter):
street: Optional[str]
country: Optional[str]
city__in: Optional[list[str]]
class Constants(Filter.Constants):
model = Address
class UserFilter(Filter):
name: Optional[str]
address: Optional[AddressFilter] = FilterDepends(with_prefix("address", AddressFilter))
class Constants(Filter.Constants):
model = User
@app.get("/users", response_model=list[UserOut])
async def get_users(user_filter: UserFilter = FilterDepends(UserFilter), db: AsyncSession = Depends(get_db)) -> Any:
# You MUST join the related model to filter on it
query = user_filter.filter(select(User).outerjoin(Address))
result = await db.execute(query)
return result.scalars().all()You can install the basic version of fastapi-filter or include specific backend support for SQLAlchemy or MongoEngine using pip extras.
# Basic version
pip install fastapi-filter
# With backends
pip install fastapi-filter[all]
# More selective
pip install fastapi-filter[sqlalchemy]
pip install fastapi-filter[mongoengine]To explore the library's capabilities, you can run the provided SQLAlchemy example using Poetry. This will demonstrate how to implement filtering and ordering in a FastAPI application.
pip install poetry
poetry install
python examples/fastapi_filter_sqlalchemy.pyTo enable ordering in your API, add an order_by field to your filter class. By default, this field accepts a list of strings.
Usage Patterns:
?order_by=age,-created_at.- for descending order or + for ascending order (default). Example: -name or +id.Customization:
ordering_field_name in the Constants class to use a different name in the query string.field_validator on the order_by field to ensure users only sort by allowed columns.class UserFilter(Filter):
class Constants(Filter.Constants):
model = User
ordering_field_name = "custom_order_by"
custom_order_by: Optional[list[str]]
# Usage in endpoint:
# query = user_filter.sort(query)
# Valid URL:
# /users?custom_order_by=age,-created_atWhen passing a filter class to a FastAPI endpoint, use FilterDepends instead of the standard Depends.
FilterDepends provides two key benefits:
list filter fields into str so they can be correctly displayed and used in the Swagger UI.ValidationError into a FastAPI HTTPException with a 422 Unprocessable Entity status code.Limitation: FilterDepends will not convert a list type to str if it is part of a union type with other types, except for None. For example, list[str] | None works, but list[str] | str will not.
@app.get("/users", response_model=list[UserOut])
async def get_users(user_filter: UserFilter = FilterDepends(UserFilter), db: AsyncSession = Depends(get_db)) -> Any:
...To enable text searching, add a search field to your filter class.
Configuration Requirements:
search, but you can override this by setting search_field_name in the Constants class.search_model_fields (a list of strings) in the Constants class.Usage:
?search=Johnny or ?custom_name_for_search=Johnny.class UserFilter(Filter):
class Constants(Filter.Constants):
model = User
search_field_name = "custom_name_for_search"
search_model_fields = ["name", "email"]
@app.get("/users")
async def get_users(user_filter: UserFilter = FilterDepends(UserFilter)):
query = select(User)
query = user_filter.sort(query) # Note: sort() is used to apply the search/order logic to the query
...Ensure your environment meets the following requirements:
Required Dependencies:
>=3.9, <4.0>=0.100, <1.0>=2.0.0, <3.0.0Optional Backend Dependencies:
>=0.24.1, <0.28.0>=1.4.36, <2.1.0fastapi_filter supports the following operators for field filtering:
neq: Not equalgt: Greater thangte: Greater than or equalin: In a list (passed as a comma-separated string, e.g., ?age__in=1,3,5)isnull: Is nulllt: Less thanlte: Less than or equalnot / ne: Not equalnot_in / nin: Not in a listlike / ilike: Pattern matchingNote for MySQL users: The in filter excludes None values.
The fastapi_filter package exports FilterDepends and with_prefix to facilitate dependency injection and prefixing for filters in FastAPI routes. These are the primary entry points for setting up filtering logic.
from fastapi_filter import FilterDepends, with_prefix