Skip to content

Chapter 2 · First App and Auto-Generated Documentation ​

Chapter goals: Master the correspondence between path operation decorators and HTTP verbs, understand route matching order, and learn to use the three auto-generated artifacts: /docs, /redoc, and openapi.json.

2.1 Path Operation Decorators ​

A "path operation" refers to "which HTTP verb accesses which path." FastAPI declares them with decorators:

python
from fastapi import FastAPI

app = FastAPI()


@app.get("/items")        # GET    — read resources
def list_items():
    return [{"id": 1, "name": "apple"}]


@app.post("/items")      # POST   — create a resource
def create_item():
    return {"created": True}


@app.put("/items/{item_id}")    # PUT    — full replacement
def replace_item(item_id: int):
    return {"replaced": item_id}


@app.patch("/items/{item_id}")  # PATCH  — partial update
def update_item(item_id: int):
    return {"patched": item_id}


@app.delete("/items/{item_id}") # DELETE — remove
def remove_item(item_id: int):
    return {"deleted": item_id}

@app.get("/items") tells FastAPI: "when a GET /items request arrives, call the function below and send back the return value as JSON." Other available verbs are head, options, trace — but the five above cover 99% of REST API usage.

Decorator parameters

Each decorator supports response_model, status_code, tags, summary, and other parameters (introduced from Chapter 6 onward). They affect only documentation and response behavior, not route matching itself.

2.2 Route Matching Order: Top to Bottom ​

FastAPI tries routes in declaration order. This creates a classic pitfall:

python
from fastapi import FastAPI

app = FastAPI()


# ❌ Wrong: /users/me declared AFTER /users/{user_id}
@app.get("/users/{user_id}")
def read_user(user_id: str):
    return {"user_id": user_id}


@app.get("/users/me")
def read_current_user():
    # Never reached! A request to GET /users/me
    # matches /users/{user_id} first, with user_id="me"
    return {"user": "the authenticated user"}

The fix is simple — static paths must be declared before parameterized ones:

python
from fastapi import FastAPI

app = FastAPI()


# ✅ Correct: static path declared first
@app.get("/users/me")
def read_current_user():
    return {"user": "the authenticated user"}


@app.get("/users/{user_id}")
def read_user(user_id: str):
    return {"user_id": user_id}

This is not a FastAPI bug — it is a shared rule of all ordered-matching routers (Express, Flask in some scenarios behave the same way).

2.3 Automatic Response Serialization ​

Path functions can return dict, list, scalars, Pydantic models, or even ORM objects — FastAPI auto-converts to JSON:

python
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    price: float


@app.get("/dict-demo")
def as_dict():
    return {"ok": True, "code": 0}          # dict → JSON object


@app.get("/list-demo")
def as_list():
    return [1, 2, 3]                        # list → JSON array


@app.get("/model-demo", response_model=Item)
def as_model():
    # Pydantic model → JSON (via Pydantic's Rust-powered serializer, extremely fast)
    return Item(name="pen", price=3.5)

2.4 Auto-Generated Documentation: /docs, /redoc, openapi.json ​

Once routes are declared, FastAPI automatically generates interactive documentation at three endpoints:

URLWhat It Shows
/docsSwagger UI — interactive form-based API explorer
/redocReDoc — clean, scrollable reference documentation
/openapi.jsonRaw OpenAPI 3 schema (machine-readable)

Visit http://localhost:8000/docs after starting the app — you will see every route with its parameters, request body schema, and response model, all auto-generated from your code. Click "Try it out" to send real requests from the browser.

2.5 Chapter Summary ​

  • Five REST verbs: @app.get/post/put/patch/delete; each declares one path operation;
  • Route matching is top-to-bottom: static paths before parameterized ones;
  • Return values auto-serialize to JSON; response_model filters output;
  • /docs (Swagger UI) and /redoc are free, auto-generated, and interactive.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What happens if you declare /users/{user_id} before /users/me?

2. What URL shows the interactive Swagger UI?

3. Which decorator handles partial resource updates?

4. What does returning a Pydantic BaseModel from a route do automatically?

🛠️ Hands-On Exercises ​

  1. Create an app with CRUD routes for /items (GET list, POST create, GET by ID, PUT update, DELETE); open /docs and use the interactive UI to test each endpoint.
  2. Deliberately reverse the declaration order of /items/{item_id} and /items/special; observe which one matches /items/special in /docs.
  3. Export the raw schema with curl http://localhost:8000/openapi.json | jq .paths and verify all routes appear.

Proceed to Chapter 3: Path Parameters and Query Parameters.