fastapi-filter

repository·main·Indexed 43 days ago

https://github.com/arthurio/fastapi-filter

A 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.

Tokens
2K
Snippets
7
Records
10
Agent score
56%

What's inside fastapi-filter

  1. Filter with related models using with_prefix

    main

    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()
  2. Install fastapi-filter

    main

    You can install the basic version of fastapi-filter or include specific backend support for SQLAlchemy or MongoEngine using pip extras.

    Installation Options

    • Basic version: Installs only the core library.
    • With all backends: Installs core plus SQLAlchemy and MongoEngine support.
    • Selective installation: Install only the specific backend you need.
    # 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]
  3. Run the SQLAlchemy example

    main

    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.py
  4. Configure Order By filtering

    main

    To 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:

    • Query Parameter: Pass a comma-separated list of strings: ?order_by=age,-created_at.
    • Direction: Prefix a field with - for descending order or + for ascending order (default). Example: -name or +id.

    Customization:

    • Rename the field: Set ordering_field_name in the Constants class to use a different name in the query string.
    • Restrict fields: Use a Pydantic 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_at
  5. How to use FilterDepends in FastAPI endpoints

    main

    When passing a filter class to a FastAPI endpoint, use FilterDepends instead of the standard Depends.

    FilterDepends provides two key benefits:

    1. Swagger UI Compatibility: It converts list filter fields into str so they can be correctly displayed and used in the Swagger UI.
    2. Error Handling: It automatically converts 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:
        ...
  6. Configure Search filtering

    main

    To enable text searching, add a search field to your filter class.

    Configuration Requirements:

    1. Field Name: The default is search, but you can override this by setting search_field_name in the Constants class.
    2. Target Fields: You must define which model columns/fields should be searched by setting search_model_fields (a list of strings) in the Constants class.

    Usage:

    • Pass a single string via the query parameter: ?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
        ...
  7. Check fastapi-filter compatibility

    main

    Ensure your environment meets the following requirements:

    Required Dependencies:

    • Python: >=3.9, <4.0
    • FastAPI: >=0.100, <1.0
    • Pydantic: >=2.0.0, <3.0.0

    Optional Backend Dependencies:

    • MongoEngine: >=0.24.1, <0.28.0
    • SQLAlchemy: >=1.4.36, <2.1.0
  8. Supported Filter Operators

    main

    fastapi_filter supports the following operators for field filtering:

    • neq: Not equal
    • gt: Greater than
    • gte: Greater than or equal
    • in: In a list (passed as a comma-separated string, e.g., ?age__in=1,3,5)
    • isnull: Is null
    • lt: Less than
    • lte: Less than or equal
    • not / ne: Not equal
    • not_in / nin: Not in a list
    • like / ilike: Pattern matching

    Note for MySQL users: The in filter excludes None values.

  9. Import FilterDepends and with_prefix from fastapi_filter

    main

    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