Search code examples
pythonfastapi

Is it possible to pass Path arguments into FastAPI dependency functions?


Is there any way for a FastAPI "dependency" to interpret Path parameters?

I have a lot of functions of the form:

@app.post("/item/{item_id}/process", response_class=ProcessResponse)
async def process_item(item_id: UUID, session: UserSession = Depends(security.user_session)) -> ProcessResponse:
    item = await get_item(client_id=session.client_id, item_id=item_id)
    await item.process()

Over and over, I need to pass in [multiple] arguments to fetch the required item before doing something with it. This is very repetitive and makes the code very verbose. What I'd really like to do is pass the item in as an argument to the method.

Ideally I'd like to make get_item a dependency or embed it somehow in the router. This would dramatically reduce the repetitive logic and excessively verbose function arguments. The problem is that some critical arguments are passed by the client in the Path.

Is it possible to pass Path arguments into a dependency or perhaps execute the dependency in the router and pass the result?


Solution

  • A FastAPI dependency function can take any of the arguments that a normal endpoint function can take.

    So in a normal endpoint you might define a path parameter like so:

    from fastapi import FastAPI
    
    app = FastAPI()
    
    
    @app.get("/items/{item_id}")
    async def read_item(item_id):
        return {"item_id": item_id}
    

    Now if you want to use that parameter in a dependency, you can simply do:

    from fastapi import Depends, FastAPI
    
    app = FastAPI()
    
    async def my_dependency_function(item_id: int):
        return {"item_id": item_id}
    
    
    @app.get("/items/{item_id}")
    async def read_item(item_id: int, my_dependency: dict = Depends(my_dependency_function)):
        return my_dependency
    

    The parameters will simply be passed on through to the dependency function if they are present there. You can also use things like Path and Query within the dependency function to define where these are coming from.

    It will just analyze the request object to pull these values.

    Here is an example using the Path function from FastAPI:

    from fastapi import Depends, FastAPI, Path
    
    app = FastAPI()
    
    async def my_dependency_function(item_id: int = Path(...)):
        return {"item_id": item_id}
    
    
    @app.get("/items/{item_id}")
    async def read_item(my_dependency: dict = Depends(my_dependency_function)):
        return my_dependency
    

    As for your concern of implementing it as a dependency in the router, you can do something like this when creating the router:

    items_router = APIRouter(
        prefix="/items",
        tags=["items"],
        dependencies=[Depends(my_dependency_function)],
    )
    

    Or you can do it when you run include_router on the app like:

    app.include_router(
        items_router,
        prefix="/items",
        dependencies=[Depends(my_dependency_function)],
    )
    

    For more on dependencies and more examples like this see https://fastapi.tiangolo.com/tutorial/dependencies/