3.6 KiB
3.6 KiB
FastAPI – Query Parameters
This document demonstrates how to use query parameters in FastAPI using multiple typing styles, including:
- Native Python union types (
str | None) OptionalfromtypingAnnotatedwithQueryvalidation
Example Application
Create or update main.py with the following content:
from fastapi import FastAPI, Query
from typing import Optional, Annotated
app = FastAPI()
users = [
{"name": "abbas", "age": 20},
{"name": "abbas", "age": 32},
{"name": "abbas", "age": 54},
{"name": "abbas", "age": 15},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/")
def home_page():
return {"msg": "API is working"}
@app.get("/user")
def get_users(target_name: str | None = None):
if target_name:
return [item for item in users if item["name"] == target_name]
return users
@app.get("/user2")
def get_users_optional(target_name: Optional[str] = None):
if target_name:
return [item for item in users if item["name"] == target_name]
return users
@app.get("/user3")
def get_users_annotated(
target_name: Annotated[str | None, Query(max_length=50)] = None
):
if target_name:
return [item for item in users if item["name"] == target_name]
return users
Query Parameter Overview
Query parameters are key-value pairs appended to the URL after ?.
Example:
/user?target_name=abbas
Defined Endpoints
1. Basic Query Parameter (Python Union Type)
@app.get("/user")
def get_users(target_name: str | None = None):
- Uses Python 3.10+ union syntax
target_nameis optional- If not provided, all users are returned
Example Request:
GET /user?target_name=abbas
2. Optional Query Parameter (typing.Optional)
@app.get("/user2")
def get_users_optional(target_name: Optional[str] = None):
- Uses
Optional[str]for compatibility with older Python versions - Behavior is identical to the first endpoint
Example Request:
GET /user2?target_name=abbas
3. Validated Query Parameter (Annotated + Query)
@app.get("/user3")
def get_users_annotated(
target_name: Annotated[str | None, Query(max_length=50)] = None
):
-
Uses
Annotatedfor metadata binding -
Adds validation rules:
max_length=50
-
Automatically returns validation errors if constraints are violated
Example Invalid Request:
GET /user3?target_name=verylongnamethatexceedslimit...
Response:
{
"detail": [
{
"type": "string_too_long",
"loc": ["query", "target_name"],
"msg": "String should have at most 50 characters",
"input": "..."
}
]
}
Example Responses
Filtered Response
[
{"name": "abbas", "age": 20},
{"name": "abbas", "age": 32},
{"name": "abbas", "age": 54},
{"name": "abbas", "age": 15}
]
Default Response (No Query Parameter)
[
{"name": "abbas", "age": 20},
{"name": "abbas", "age": 32},
{"name": "abbas", "age": 54},
{"name": "abbas", "age": 15},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19}
]
Running the Application
Start the service using uvicorn:
uvicorn main:app --reload
Best Practices
- Use query parameters for filtering and searching
- Always provide defaults for optional parameters
- Use
Query()for validation and constraints - Return full datasets when no filters are applied
- Avoid large in-memory datasets in production
- Use pagination for large result sets
- Combine query parameters with database queries in real systems