How to Use FastAPI Dependency Injection for Clean Code

How to Use FastAPI Dependency Injection for Clean Code

FastAPI is a modern web framework for building APIs with Python 3.6+ based on standard Python type hints. One of its most powerful features is dependency injection, which facilitates cleaner and more maintainable code. In this article, we will explore how to effectively use FastAPI's dependency injection system.

What is Dependency Injection?

Dependency injection is a design pattern that allows the creation of dependent objects outside of a class and provides those objects to a class through various ways. In the context of FastAPI, this means that you can define dependencies and pass them to your routes or other components in a straightforward manner, promoting cleaner and more modular code.

Creating Dependencies in FastAPI

To create a dependency in FastAPI, define a function that will serve as the dependency. This function can return any data you need, such as database connections, configuration settings, or validation logic.

from fastapi import FastAPI, Depends
app = FastAPI()
def get_query(query: str = None):
    return query

In this example, the function get_query accepts a query string parameter and returns it.

Injecting Dependencies into Endpoints

Once you have defined your dependencies, you can easily inject them into your endpoints using the Depends function. This function takes your dependency function as an argument.

@app.get("/")
async def read_root(query: str = Depends(get_query)):
    return {"query": query}

In this code snippet, the query parameter in the read_root function automatically calls the get_query function, allowing you to use its return value directly.

Using Classes as Dependencies

FastAPI also allows dependencies to be defined as classes. By using classes, you can encapsulate related data and behavior more effectively. Here’s how to do this:

class QueryModel:
    def __init__(self, query: str = None):
        self.query = query
def get_query_model(query: str = None):
    return QueryModel(query)

To use this class-based dependency within a route, follow this pattern:

@app.get("/items/")
async def read_items(query_model: QueryModel = Depends(get_query_model)):
    return {"query": query_model.query}

Handling Dependencies with Database Connections

Dependency injection is particularly useful when dealing with database connections. You can create a dependency that establishes a database connection for each request. Here’s an example using an async database connection:

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite+aiosqlite:///./test.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)
async def get_db() -> AsyncSession:
    async with async_session() as session:
        yield session

Now, you can use this database session as a dependency in your routes:

@app.post("/items/")
async def create_item(item: Item, db: AsyncSession = Depends(get_db)):
    db.add(item)
    await db.commit()
    return item

Benefits of Using Dependency Injection in FastAPI

Using FastAPI's dependency injection offers several benefits:

  • Reusability: Dependencies can be reused across different routes, reducing code duplication.
  • Testability: It simplifies unit testing by allowing you to replace real dependencies with mock ones.
  • Separation of Concerns: It keeps your route logic clean by separating business logic from request handling.
  • Easy to Manage: You can easily manage configurations and services through your dependency functions.

Conclusion

FastAPI's dependency injection feature is a powerful tool for building clean and maintainable code. By leveraging dependencies, you can improve the structure of your application, making it easier to read, test, and expand. Whether you're managing query parameters, database connections, or complex configurations, FastAPI’s approach ensures that your code remains organized and easy to