Module 2 · FastAPI · Drills

Drills: FastAPI Core

Reading is not knowing. Type every route yourself, run it, and click it in /docs before you reveal the solution. Effortful recall is the point.

How to use this page Each drill is a small route to add to a main.py. Write it first, then run fastapi dev main.py and test it on the /docs page — fill the parameters, hit Execute, read the response. Only then click “Show solution” to compare. Tick each box as you go; your progress is saved in this browser.

A · Warm-up reps Basic

Drill 1 path param

Write a GET /documents/{doc_id} route. Type doc_id as an int and return it as JSON. Then test /documents/abc in /docs and watch FastAPI reject it.

Show solution
@app.get("/documents/{doc_id}")
def get_document(doc_id: int):
    return {"doc_id": doc_id}
# /documents/7  → {"doc_id": 7}
# /documents/abc → 422 automatic validation error

Drill 2 Pydantic + POST

Define a Pydantic Document model with title: str and pages: int. Write a POST /documents that takes one and echoes it back.

Show solution
from pydantic import BaseModel

class Document(BaseModel):
    title: str
    pages: int

@app.post("/documents")
def create_document(doc: Document):
    return doc

In /docs the request body form is generated from the model — POST {"title": "Intro", "pages": 12}.

Drill 3 query param

Write a GET /documents that accepts an optional limit query parameter defaulting to 10, and returns it.

Show solution
@app.get("/documents")
def list_documents(limit: int = 10):
    return {"limit": limit}
# /documents          → {"limit": 10}
# /documents?limit=5  → {"limit": 5}

B · Stretch Intermediate

Drill 4 Field validation

Add a constraint to the Document model so title can't be empty (min_length=1) and pages must be positive (gt=0). Try posting {"title": "", "pages": 0} in /docs and read the 422.

Show solution
from pydantic import BaseModel, Field

class Document(BaseModel):
    title: str = Field(..., min_length=1)
    pages: int = Field(..., gt=0)

The ... means "required". The 422 response names the exact field and rule that failed — you wrote no validation code.

Drill 5 404

Given an in-memory documents = {} dict, write GET /documents/{doc_id} that raises a 404 when the id isn't present, and returns the document otherwise.

Show solution
from fastapi import HTTPException

documents = {}

@app.get("/documents/{doc_id}")
def get_document(doc_id: int):
    if doc_id not in documents:
        raise HTTPException(404, "Document not found")
    return documents[doc_id]

raise short-circuits the function — nothing after it runs, and the client gets {"detail": "Document not found"} with status 404.

C · Build challenge Build

Mini-project Take the DocChat CRUD API from the lesson and add the one route it's missing: an update. Write PUT /documents/{doc_id} that replaces an existing document with a new Document body, raises 404 if the id doesn't exist, and returns the updated document. This completes full Create-Read-Update-Delete.

Build · PUT update endpoint

Assume the lesson's documents dict and Document model are already defined. Add the PUT route.

Show solution
@app.put("/documents/{doc_id}")
def update_document(doc_id: int, doc: Document):
    if doc_id not in documents:
        raise HTTPException(404, "Document not found")
    documents[doc_id] = doc
    return {"id": doc_id, "document": doc}

Note the signature takes both a path param (doc_id) and a body (doc). FastAPI pulls each from the right place — the int from the URL, the model from the JSON body — because of their types. Test it in /docs: create a document, note its id, then PUT a changed body to that id and GET it back to confirm.

D · Rapid recall Flashcards

Click a card to flip it. Say the answer out loud before you flip — that's the rep that builds storage strength.

What does a Pydantic BaseModel do?
Declares a typed schema that FastAPI uses to parse and validate the request body — and to generate docs.
click to flip
URL of the interactive Swagger docs?
/docs (and /redoc for the reference view).
click to flip
How do you return an error like 404?
raise HTTPException(404, "...") — the framework formats the JSON response.
click to flip
Path param vs query param?
Path = in the URL (/documents/{id}), identifies a resource. Query = after ?, filters/paginates it.
click to flip
What does response_model do?
Declares and shapes the output — FastAPI filters the return value to match, hiding extra fields.
click to flip
When use async def for a route?
When the body awaits I/O (DB, network, LLM). Plain def for quick synchronous work.
click to flip

E · Self-check before moving on

Tick each only if you can do it without looking:

Next Full CRUD working and clicking happily in /docs? You have a real API. Next we make it production-shaped — dependencies, routers, middleware, and auth-ready structure: Lesson 2.2 — FastAPI Advanced.