Nested Models — Real-World Payloads
IntermediateModels compose: a field typed as another BaseModel nests an object, list[Model] nests an array, and validation runs recursively with error paths like items.1.qty — plus rich types (EmailStr, UUID, datetime) and Enums for free.
Overview
Real payloads are trees: an order has a delivery address and a list of items, each item has its own fields. Pydantic composes naturally — type a field as Address and the JSON must contain a valid Address object; type it list[OrderItem] and every element is validated, with failure locations that index into the array (items → 1 → qty). Rich types raise the floor further: EmailStr, HttpUrl, UUID, datetime, and Decimal parse and validate formats you would otherwise regex by hand, and str-Enums lock fields to fixed vocabularies. Define each nested model once and reuse it across endpoints — the models become your API vocabulary and the docs render them as an interlinked schema.
Objects in Objects, Lists of Objects
Compose models like types. Validation is recursive; the loc path in a 422 walks the tree including list indexes, so clients can highlight exactly the third item's qty field.
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Address(BaseModel):
line1: str
city: str
pincode: str = Field(pattern=r"^[1-9][0-9]{5}$")
class OrderItem(BaseModel):
sku: str
name: str
qty: int = Field(ge=1, le=20)
price: float = Field(gt=0)
class OrderIn(BaseModel):
customer: str
address: Address # nested object
items: list[OrderItem] = Field(min_length=1) # non-empty array
coupon: str | None = None
@app.post("/orders")
def place_order(order: OrderIn):
total = sum(i.qty * i.price for i in order.items)
return {"city": order.address.city, "items": len(order.items), "total": total}
# Payload:
# {"customer": "Ravi",
# "address": {"line1": "12 FC Road", "city": "Pune", "pincode": "411005"},
# "items": [{"sku": "S1", "name": "Kurta", "qty": 2, "price": 799},
# {"sku": "S2", "name": "Mojari", "qty": 0, "price": 1299}]}
#
# → 422: {"loc": ["body", "items", 1, "qty"],
# "msg": "Input should be greater than or equal to 1"}
# ← the SECOND item's qty, pinpointed. Frontend can highlight that row.Rich Types and Enums — Stop Writing Regexes
EmailStr, HttpUrl, UUID, datetime, and Decimal validate formats properly (install email-validator for EmailStr). str-Enums constrain vocabulary fields and show as dropdowns in /docs.
from datetime import datetime
from decimal import Decimal
from enum import Enum
from uuid import UUID
from pydantic import BaseModel, EmailStr, HttpUrl
class PaymentMode(str, Enum):
upi = "upi"
card = "card"
netbanking = "netbanking"
cod = "cod"
class PaymentIn(BaseModel):
txn_id: UUID # "6fa0f7…-…" parsed to UUID
email: EmailStr # real email validation
amount: Decimal # exact money math — never float in ledgers
mode: PaymentMode # only the 4 values above
receipt_url: HttpUrl | None = None # scheme + host validated
paid_at: datetime # "2026-07-11T14:30:00+05:30" → aware dt
p = PaymentIn(
txn_id="6fa0f7f4-3c1e-4c8e-9b2a-1e5d3c7a9b01",
email="asha@nitk.edu.in",
amount="1499.50", # string in → Decimal("1499.50")
mode="upi",
paid_at="2026-07-11T14:30:00+05:30",
)
print(p.paid_at.tzinfo) # timezone-aware, IST offset kept
print(p.model_dump_json()) # UUID/Decimal/datetime serialize cleanly
# mode="wallet" → 422 "Input should be 'upi', 'card', 'netbanking' or 'cod'"
# In /docs, mode renders as a dropdown — the Enum IS the documentation.Key Points to Remember
- 1Nest by typing: field: Address, items: list[OrderItem], recursive validation free
- 2422 loc paths walk the tree with list indexes — clients can pinpoint bad rows
- 3EmailStr/HttpUrl/UUID/datetime/Decimal replace hand-rolled format regexes
- 4str-Enum fields lock vocabulary and render as dropdowns in /docs
Interview Questions
Sign in to ask AriaModel a food-delivery order payload: restaurant, items with quantities, delivery address.
Why Decimal instead of float for the amount field in a payments API?
One item in a 50-item order payload is invalid — what exactly does the client receive?
Ask Aria about Nested Models — Real-World Payloads
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.