CodingNeed.

2 · Data and boundaries · 30 MIN

FastAPI request and response models

Input and output models can have different responsibilities.

Pydantic validates the request before the route function runs. Field constraints describe acceptable lengths and numeric ranges, while forbidding extra fields rejects accidental extra fields. A separate output model limits what the endpoint serializes. Do not return a database object with password hashes and assume the browser will hide unwanted fields. This preview endpoint uses no account data or persistence; adapt it to a write only after adding authenticated ownership and request-size limits at the application or proxy layer.

Inspect the generated /docs contract.

Read the example

# main.py
from fastapi import FastAPI
from pydantic import BaseModel, ConfigDict, Field
app = FastAPI()
class PlanInput(BaseModel):
    model_config = ConfigDict(extra="forbid")
    title: str = Field(min_length=3, max_length=80)
    weekly_goal: int = Field(ge=1, le=20, strict=True)
class PlanPreview(BaseModel):
    title: str
    weekly_goal: int
@app.post("/preview", response_model=PlanPreview)
def preview(plan: PlanInput):
    return PlanPreview(title=plan.title, weekly_goal=plan.weekly_goal)
Check the expected output
A valid body produces the preview; a numeric string goal, extra field or out-of-range goal produces validation status 422.

Your challenge

Add trimmed-title validation that rejects whitespace-only values, then test input coercion and response field filtering.

Solution cost: O(f + m) validation and serialization. time · O(f + m) request and response model data. space

Common trap

CORS settings do not authenticate a caller or authorize a record.

Study the project implementation
# main.py
from fastapi import FastAPI
from pydantic import BaseModel, ConfigDict, Field
app = FastAPI()
class PlanInput(BaseModel):
    model_config = ConfigDict(extra="forbid")
    title: str = Field(min_length=3, max_length=80)
    weekly_goal: int = Field(ge=1, le=20, strict=True)
class PlanPreview(BaseModel):
    title: str
    weekly_goal: int
@app.post("/preview", response_model=PlanPreview)
def preview(plan: PlanInput):
    return PlanPreview(title=plan.title, weekly_goal=plan.weekly_goal)

Further reading: Official documentation

Next lesson: FastAPI dependencies and cleanup

Essential cookies keep your account signed in. Optional analytics is not configured on this site. Your choice does not affect access to lessons.

Read the Privacy Policy. You can change this choice in the footer.