AtomLearnAtomLearn
DashboardGoalsPathAchievementsReviewSign In
DashboardFastAPIFastAPI Fundamentals
FastAPINot Started

FastAPI Fundamentals

Path & query params, Pydantic request bodies, dependency injection, and async endpoints

0%
Knowledge0%
Learn & Drill
Fluency0%
Drill & Speed
Retention0%
Mastery & Review
Confidence0%
All modes
Practice
Knowledge
Fluency
Retention

Knowledge Debt detected

You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.

Explanation

FastAPI is the dominant modern Python web framework — built on Starlette + Pydantic, with automatic validation and interactive docs generated from your type hints.

Minimal app:

python from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"message": "Hello World"} # Run with: uvicorn main:app --reload

Path and query parameters — type hints drive validation:

python from typing import Optional @app.get("/items/{item_id}") def get_item(item_id: int, q: Optional[str] = None): return {"item_id": item_id, "q": q} - item_id is a **path parameter** — it appears in {} in the route. int means FastAPI validates and converts it, returning a 422 error if the URL segment isn't a valid int. - q is a **query parameter** (?q=...) — any function parameter not in the path or declared as a body model becomes a query parameter. Optional[str] = None` makes it optional.

Request bodies with Pydantic:

python from pydantic import BaseModel class Item(BaseModel): name: str price: float in_stock: bool = True @app.post("/items") def create_item(item: Item): return {"name": item.name, "total": item.price} FastAPI parses the JSON body, validates field types, and gives you a typed Item` object. Invalid bodies (missing fields, wrong types) return 422 automatically — no manual validation code needed.

Dependency Injection with Depends():

python from fastapi import Depends, HTTPException def get_db(): db = SessionLocal() try: yield db finally: db.close() def get_current_user(token: str = Depends(oauth2_scheme)): user = decode_token(token) if not user: raise HTTPException(status_code=401, detail="Invalid token") return user @app.get("/profile") def read_profile(user=Depends(get_current_user), db=Depends(get_db)): return user Depends()` tells FastAPI to call a function (or generator, for setup/teardown) and inject its return value as an argument — used for DB sessions, auth checks, and shared logic across routes.

Async endpoints:

python @app.get("/users/{user_id}") async def get_user(user_id: int): user = await db.fetch_one("SELECT * FROM users WHERE id = :id", {"id": user_id}) return user Use async def when the body awaits I/O (DB, HTTP calls). A plain def` endpoint still works fine — FastAPI runs it in a thread pool.

Route ordering matters:

python @app.get("/users/me") # must come first def read_current_user(): return {"user": "me"} @app.get("/users/{user_id}") # would otherwise match "/users/me" first def read_user(user_id: int): return {"user_id": user_id}

Automatic docs: every FastAPI app gets interactive docs at /docs (Swagger UI) and /redoc, generated entirely from your type hints and Pydantic models.

Examples

CRUD endpoint with path, query params, and a Pydantic body

item_id (path) and include_tax (query) are validated by type hints; the POST body is validated against the Item model

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    in_stock: bool = True

@app.get("/items/{item_id}")
def get_item(item_id: int, include_tax: Optional[bool] = False):
    price = 19.99
    if include_tax:
        price *= 1.1
    return {"item_id": item_id, "price": price}

@app.post("/items", status_code=201)
def create_item(item: Item):
    return {"created": item.name, "price": item.price}

Dependency injection for DB session and auth

Both dependencies run before the route body; get_db cleans up the session afterward even if the route raises

from fastapi import Depends, HTTPException, FastAPI

app = FastAPI()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

def get_current_user(token: str = Depends(oauth2_scheme)):
    user = decode_token(token)
    if user is None:
        raise HTTPException(status_code=401, detail="Invalid or missing token")
    return user

@app.get("/orders")
def list_orders(user=Depends(get_current_user), db=Depends(get_db)):
    return db.query(Order).filter(Order.user_id == user.id).all()

How well did you understand this?

Next in FastAPI

FastAPI JWT Auth

Continue