Lesson 2 · FastAPI deep dive
FastAPI Tutorial #2: Path & Query Parameters Explained
Video two of the eighteen-part series: pulling real data straight out of the URL. Typed path parameters, query parameters, defaults, and validation. Let's…
- CourseFastAPI deep dive
- Lesson2 of 12
- Video14 min
- FormatJupyter notebook · 10 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbFastAPI Deep-Dive, Video 2: Path and Query Parameters#
- Video two of the eighteen-part series: pulling real data straight out of the URL.
- Typed path parameters, query parameters, defaults, and validation.
- Let's get into it.
Part 1: Path Parameters - Typed, Automatic Conversion#
from fastapi import FastAPI
from fastapi.testclient import TestClient
app = FastAPI()
@app.get('/items/{item_id}')
def read_item(item_id: int):
return {'item_id': item_id, 'type': type(item_id).__name__}
client = TestClient(app)
print(client.get('/items/42').json())
Part 2: Path Parameter Validation Errors#
response = client.get('/items/not-a-number')
print(response.status_code)
print(response.json())
Part 3: Query Parameters Basics#
@app.get('/search')
def search(q: str = 'default query', limit: int = 10):
return {'q': q, 'limit': limit}
print(client.get('/search').json())
print(client.get('/search?q=fastapi&limit=5').json())
Part 4: Required vs Optional Query Parameters#
@app.get('/required-search')
def required_search(q: str):
return {'q': q}
print(client.get('/required-search?q=hello').json())
missing = client.get('/required-search')
print(missing.status_code)
Part 5: Type Conversion - bool and Other Types#
@app.get('/toggle')
def toggle(active: bool = False):
return {'active': active}
print(client.get('/toggle?active=true').json())
print(client.get('/toggle?active=0').json())
print(client.get('/toggle').json())
Part 6: Combining Path and Query Parameters#
@app.get('/users/{user_id}/orders')
def user_orders(user_id: int, status: str = 'all', page: int = 1):
return {'user_id': user_id, 'status': status, 'page': page}
print(client.get('/users/7/orders').json())
print(client.get('/users/7/orders?status=shipped&page=2').json())
Part 7: Optional Query Parameters with None#
@app.get('/filter')
def filter_items(category: str | None = None):
if category is None:
return {'filter': 'none applied'}
return {'filter': category}
print(client.get('/filter').json())
print(client.get('/filter?category=books').json())
Part 8: Enum Path Parameters - a Fixed Set of Values#
from enum import Enum
class SortOrder(str, Enum):
asc = 'asc'
desc = 'desc'
@app.get('/sorted-items/{order}')
def sorted_items(order: SortOrder):
return {'order': order.value}
print(client.get('/sorted-items/asc').json())
print(client.get('/sorted-items/sideways').status_code)
Part 9: Multiple Values for the Same Query Parameter#
from fastapi import Query
@app.get('/tags')
def get_by_tags(tag: list[str] = Query(default=[])):
return {'tags': tag}
print(client.get('/tags?tag=python&tag=fastapi&tag=api').json())
print(client.get('/tags').json())
Part 10: A Real Pattern - a Filtered Search Endpoint#
class Category(str, Enum):
electronics = 'electronics'
books = 'books'
all = 'all'
@app.get('/stores/{store_id}/products')
def store_products(
store_id: int,
category: Category = Category.all,
min_price: float | None = None,
in_stock: bool = True
):
return {
'store_id': store_id, 'category': category.value,
'min_price': min_price, 'in_stock': in_stock
}
print(client.get('/stores/3/products').json())
print(client.get('/stores/3/products?category=books&min_price=9.99&in_stock=false').json())
Wrap-Up: What You Learned#
- A function parameter matching a {curly-brace} path segment becomes a path parameter, converted by its type hint.
- An invalid value for a typed path parameter triggers an automatic 422 Unprocessable Entity error with details.
- Any parameter not in the path template becomes a query parameter; a default value makes it optional.
- A query parameter with no default becomes required, triggering 422 if it's missing.
- Query parameters support bool, float, and other basic types, with common truthy strings recognized for bool.
- Path and query parameters combine freely in one endpoint; FastAPI infers which is which from the path template.
- str | None with a default of None makes a query parameter optional without forcing a fallback value.
- Typing a parameter as a Python Enum restricts it to declared members and renders as a dropdown in the docs.
- Typing a query parameter as list[str] collects repeated occurrences of the same parameter name into one list.
- That wraps up path and query parameters. Next up: Request Body and Pydantic Models.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



