FastAPI: rebuilding Week 2's notes API#
Goal#
Take the class and type-hint fluency notes/01-classes.md through notes/03-dataclasses.md built, and the "read real docs cold" habit project/README.md tested, and use both for the actual payoff: a real web framework built entirely around typed classes doing your validation for you. FastAPI is that framework, and the fastest way to see what it actually buys you is to rebuild something you've already built once, by hand, without it.
The app you're rebuilding#
Back in Week 2, you built a small Flask API for managing notes. The finished version, solutions/notes_api.py, has five endpoints:
- GET /notes, list every note.
- GET /notes/<note_id>, get one note. A 404 if the id doesn't exist.
- POST /notes, create a note. The server assigns the id; the client sends
{"text": "Buy milk"}. - PUT /notes/<note_id>, update a note's text. A 404 if the id doesn't exist.
- DELETE /notes/<note_id>, delete a note. A 404 if the id doesn't exist.
Each note is {"id": 1, "text": "Buy milk"}, and the whole list persists to a JSON file on disk (load_notes() / save_notes(notes)), so a server restart doesn't lose anything. The two routes that take a body, create_note and update_note, read it by hand with request.get_json(); every id lookup, across all three routes that take one, goes through one shared find_note(note_id) helper that returns None on a miss, leaving each route to decide what "not found" means for itself.
There's one detail worth sitting with, because it's exactly the gap this sub-step closes. create_note builds the new note with body.get("text"), no check that "text" was actually sent. The solution file says so directly, in its own comment: "a more thorough app might validate this and return a 400 Bad Request instead, which is a reasonable extension to try on your own." Nobody built that extension back in Week 2, because validating a request body by hand, checking each field's presence and type, writing the error response yourself, is exactly the kind of code a total beginner shouldn't have to write yet. That's not a gap in the Week 2 project. It's the reason this sub-step exists.
Why now, not Week 2#
Week 2's own note on web frameworks already named this trade-off: FastAPI was passed over specifically because "it adds automatic data validation and interactive documentation on top of similar underlying ideas, but that extra machinery is more to understand up front than is worth it for your first-ever web service." That automatic validation runs on classes and type hints, the exact two things Weeks 0-8 deliberately never covered. Flask hasn't come up again since Week 3; if it's been a while, that recap above is meant to stand on its own, not send you hunting back through old notes first.
Do this in order#
notes/01-path-operations.mdnotes/02-request-bodies-and-validation.mdnotes/03-path-and-query-parameters.mdnotes/04-response-models-and-docs.mdproject/README.md, rebuild the notes API above for real. No walkthrough, same reasoning as../project/README.mdbefore it.
Optional, any time after the notes: the three small reps in exercises/, one for a request body model, one for a path parameter, one for a response model.
Setup#
FastAPI isn't part of the standard library. Install it along with its development tooling:
pip install "fastapi[standard]"
That gives you both the fastapi package and the fastapi command-line tool the notes below use to run an app (fastapi dev app.py), Flask's python app.py was enough on its own back in Week 2 because app.run(debug=True) was the last line of the file; a FastAPI app doesn't start itself the same way, so it needs that separate command instead.