Path operations: FastAPI's version of a route#
One decorator per method, same path#
Compare this directly to solutions/notes_api.py. Its GET /notes and POST /notes were already two separate route declarations, not one function branching on request.method:
@app.route("/notes", methods=["GET"])
def list_notes():
...
@app.route("/notes", methods=["POST"])
def create_note():
...
The FastAPI version drops the methods=[...] list and folds the method straight into the decorator's name:
@app.get("/notes")
def list_notes():
...
@app.post("/notes")
def create_note():
...
Same path, "/notes", appearing on two separate decorators. FastAPI matches a path operation by path and method together, exactly the way Flask's methods=[...] did; nothing about that matching logic actually changed, only the spelling.
Running it#
Flask's app.py ended with if __name__ == "__main__": app.run(debug=True), so python app.py was the whole story. A FastAPI file usually has no such block at all; the fastapi command-line tool (installed by pip install "fastapi[standard]") finds the app object in your file and runs it for you: fastapi dev app.py starts a live server, by default at http://127.0.0.1:8000, and reloads automatically whenever you save, the same convenience debug=True gave you before.
What used to be jsonify#
Every Flask route in notes_api.py that returns actual data wraps it in jsonify(...), because Flask needs to be told explicitly "turn this Python value into a JSON response" (the one exception, delete_note's success path, returns a plain "", 204 instead, since there's no body to convert either way). A FastAPI path operation function just returns the value directly, a dict, a list, later a pydantic model, and FastAPI handles the conversion to JSON on its own, every time, without a wrapping call.
What to watch for#
- Writing
@app.route(...)out of Flask muscle memory. FastAPI has no.route(...)method; it's always a specific verb,.get,.post,.put,.delete, and so on. - Running a FastAPI file with plain
python app.pyand getting nothing. Without anapp.run(...)-style call at the bottom, the file just defines things and exits;fastapi dev app.pyis the separate command that actually starts the server. - Assuming two decorators on the same path string are somehow one route with two methods. They're two entirely separate path operations that happen to share a path; each has its own function, its own request handling, and (starting in the next note) its own request body shape.
TL;DR#
FastAPI apps are built the same way your Week 2 Flask app was, an application object, and decorators connecting a URL to a function, just split into one decorator per HTTP method instead of Flask's single @app.route(...) plus a methods list.
FastAPI()creates your application object, the same roleFlask(__name__)played.@app.get(...),@app.post(...),@app.put(...), and@app.delete(...)replace Flask's one@app.route(path, methods=[...]); the HTTP method is part of the decorator's name now, not a list you pass in.- A path operation function's return value becomes the JSON response automatically. A plain dict or list is enough; there's no
jsonify(...)call anywhere. fastapi dev app.pyruns the app in development mode, FastAPI's answer toapp.run(debug=True): it starts a live server and reloads on every save.
from fastapi import FastAPI
app = FastAPI()
@app.get("/notes")
def list_notes():
return notes # a list, not jsonify(notes): FastAPI converts it for you
@app.post("/notes")
def create_note():
...
fastapi dev app.py