Chapter 3: Your First Application
Start with a vertical slice: route, model, service, test. Do not start with a grand architecture.
from typing import Annotated
from fastapi import FastAPI, HTTPException, Path
from pydantic import BaseModel, Field
app = FastAPI(title="RecipeVault")
class RecipeSummary(BaseModel):
id: int
title: str = Field(min_length=1, max_length=120)
servings: int = Field(ge=1, le=50)
RECIPES = {
1: RecipeSummary(id=1, title="Sourdough Pancakes", servings=4),
}
@app.get("/api/recipes/{recipe_id}", response_model=RecipeSummary)
def get_recipe(
recipe_id: Annotated[int, Path(ge=1)],
) -> RecipeSummary:
recipe = RECIPES.get(recipe_id)
if recipe is None:
raise HTTPException(status_code=404, detail="Recipe not found")
return recipe
Key ideas:
- Type hints are runtime inputs for FastAPI.
- Pydantic models describe validated data contracts.
HTTPExceptionis the normal way to stop request handling with a specific HTTP result.response_modelshapes output and OpenAPI metadata.
In .NET, you might separate DTOs, entities, services, and endpoints immediately. In Python, begin simple, then extract when there is real pressure. Python projects become hard to maintain when they are either too clever or too flat for too long.