Have you ever stared at FastAPI code, wondering how it magically knows what to do with all those function parameters? You’re not alone! FastAPI’s parameter handling system is incredibly powerful, but the way it works can feel like decoding alien tech when you’re first starting out.
Grab a coffee ☕️, and let’s demystify FastAPI parameters once and for all.
Path Parameters: Values from the URL
Let’s start with the simplest case. Path parameters come directly from the URL:
|
|
When someone visits /users/42
, FastAPI extracts 42
from the URL and passes it to your function as user_id
. The type annotation (int
) tells FastAPI to convert the string from the URL to an integer automatically.
Query Parameters: Values from ?key=value
Query parameters come from the URL query string (after the ?
):
|
|
A request to /search/?q=fastapi&limit=5
gives you {"query": "fastapi", "page": 1, "limit": 5}
. Parameters with default values (like page
and limit
) are optional.
Request Body: JSON Data
For POST, PUT, and other methods that send data, you’ll typically use Pydantic models to handle JSON:
|
|
When your API receives JSON like {"name": "Coffee Mug", "price": 12.99}
, FastAPI validates it against your model and creates a proper Python object.
Form Data & File Uploads
For handling form submissions and file uploads:
|
|
The Form(...)
and File(...)
tell FastAPI to look for these values in form data rather than JSON.
The Magic of Dependency Injection
This is where FastAPI really shines. With the Depends()
function, you can inject database connections, authentication, and more:
|
|
When FastAPI sees Depends(get_db)
, it:
- Calls the
get_db()
function - Takes what’s yielded (the database session)
- Passes it to your endpoint function
- After your function completes, it resumes
get_db()
to run the cleanup code
This pattern is perfect for resource management - connections, files, etc.
Authentication with Dependencies
A common use of dependency injection is authentication:
|
|
Here, get_current_user
checks the token and either:
- Returns a user object that’s passed to your function
- Raises an exception, preventing your function from running
Special FastAPI Parameters (No Depends Required)
FastAPI automatically recognizes certain types and injects them without needing Depends()
:
|
|
When FastAPI sees parameters typed as Request
, Response
, or BackgroundTasks
, it automatically provides the appropriate objects. That’s why in your original example, background_tasks: BackgroundTasks
didn’t need Depends()
- it’s special!
Understanding BackgroundTasks
BackgroundTasks
deserves special attention because it’s incredibly useful:
|
|
The task runs after your response is sent, allowing for faster API responses while heavy work happens in the background.
Dependency Chains: Dependencies with Dependencies
Dependencies can have their own dependencies, forming a chain:
|
|
FastAPI resolves this entire chain automatically:
- Call
get_db()
to get a database session - Pass that to
get_repository()
to get a repository - Pass that repository to your endpoint
Shared Dependencies with Dependency Caching
If you use the same dependency multiple times, FastAPI is smart enough to call it just once per request:
|
|
Even though get_db
is used twice (once directly and once in get_user
), FastAPI calls it only once.
Testing with Dependency Overrides
One of the most powerful features of dependency injection is how easy it makes testing:
|
|
By replacing get_db
with get_test_db
, all your endpoints use a test database instead.
Elegant Parameter Types with Annotated (FastAPI 0.95.0+)
For cleaner code, FastAPI now supports Annotated
from the typing
module:
|
|
This separates type information from dependency information, making your code more readable.
Putting It All Together: A Realistic Example
Here’s a comprehensive example combining multiple parameter types:
|
|
This single endpoint elegantly handles:
- Path parameters (
case_id
) - File uploads (
file
) - Database connections (
db
) - Authentication (
current_user
) - Background processing (
background_tasks
)
When to Use What
To summarize when to use each parameter type:
- Path parameters: For required values that form part of the URL
- Query parameters: For optional filters, sorting, pagination
- Request body: For complex data in POST/PUT requests
- Form data: For traditional HTML forms
- File uploads: For file handling
- Dependencies: For shared resources, authentication, and business logic
- Special types: For direct access to request/response objects and background tasks
Conclusion
FastAPI’s parameter system might seem complex at first, but once you understand it, you’ll appreciate how it simplifies API development. By automatically handling everything from URL extraction to dependency injection, FastAPI lets you focus on your business logic rather than boilerplate code.
Remember, the basic rule is:
- Path and query parameters come from the URL
- Request body comes from the request data
- Dependencies and special types are provided by FastAPI
With these concepts in mind, you’ll be building clean, maintainable APIs in no time. Happy coding! 🚀