Skillversitas

Nested Models

Real APIs have hierarchical data: an order with line items, a user with addresses, a report with nested sections. Pydantic models nest naturally, and FastAPI validates the whole structure, including lists of models, in one pass.

Nested Structures

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class Address(BaseModel):
    street: str
    city: str
    zip_code: str = Field(pattern=r"^\d{5}$")

class Customer(BaseModel):
    name: str
    email: str
    address: Address
    extra_addresses: list[Address] = []

class Order(BaseModel):
    customer: Customer
    total: float = Field(ge=0)

@app.post("/orders/")
def create_order(order: Order):
    return {"customer": order.customer.name, "total": order.total}

FastAPI validates deeply: a missing zip_code or a bad pattern in extra_addresses[1] produces a 422 pointing at that exact location.

Lists of Models

class LineItem(BaseModel):
    sku: str
    quantity: int = Field(gt=0)
    price: float = Field(ge=0)

class Cart(BaseModel):
    items: list[LineItem] = Field(min_length=1)

    @property
    def total(self) -> float:
        return sum(i.quantity * i.price for i in self.items)

Computed Fields

Use properties or model_validator to add derived data that clients should see but never send:

from pydantic import model_validator

class OrderOut(BaseModel):
    customer_name: str
    total: float
    currency: str = "USD"

    @model_validator(mode="after")
    def add_total_display(self):
        self.total_display = f"{self.total:.2f} {self.currency}"
        return self

Copying and Updating

model_copy(update={...}) produces a modified copy without mutation, which is handy when building response models:

out = order.customer.model_copy(update={"name": order.customer.name.upper()})

Summary

Model hierarchical payloads with nested Pydantic models: objects inside objects, lists of models, constraints at every level, and computed fields via properties or model_validator. FastAPI validates the entire tree and reports the exact failing field, so deep structures cost you nothing extra.