green snake
Photo by Pixabay on Pexels.com

A Beginner’s Guide to Defining Requests and Responses with FastAPI and Pydantic


📋 Article Highlights (Summary)

  • Who Is This For?
    Intermediate users who understand the basics of Python and FastAPI but want to learn data validation and type-safe API design
  • What You’ll Learn
    1. The core structure of Pydantic models (BaseModel)
    2. How to validate incoming request bodies
    3. Controlling output and generating docs with response models
    4. Setting default values, aliases, and validation rules on fields
    5. Examples of nested models, lists, and custom validators
  • Key Benefits
    • Automatically generated validation errors help you build robust, user-friendly APIs
    • Model definitions appear in the docs UI, smoothing collaboration with front-end developers

🎯 Target Audience

  • Student Engineer A (22)
    Has built simple APIs with Flask or Django, now eager to experience type hints and auto-validation
  • Professional B (30)
    Migrating in-house tool APIs to FastAPI and want stricter input checking and output formats
  • Side-Project Dev C (27)
    Wants to safely receive user input in a hobby To-Do app and auto-generate clear API specs

♿ Accessibility Considerations

  • Readability: Balanced use of kanji, hiragana, and katakana; simple furigana for key terms
  • Structured: Clear hierarchy with headings, subheadings, and bullet lists
  • Code Examples: Fixed-width, comment-annotated code blocks for better visibility
  • Navigation: “Key Takeaways” at each section’s end for screen reader users

1. Pydantic Models Basics — What Is BaseModel?

FastAPI adopts Pydantic, a library that leverages Python type hints to automate data validation and serialization. The heart of it is inheriting from BaseModel, where you only need to specify field types to get validation and defaults out of the box.

from pydantic import BaseModel

class Item(BaseModel):
    name: str           # Required string
    price: float        # Required float
    is_offer: bool = False  # Optional (default: False)

Key Takeaways

  • Inherit from BaseModel to define your class
  • Type hints drive validation and serialization
  • Fields with default values are treated as optional

2. Applying Models to Request Bodies

2.1 Annotating FastAPI Endpoint Arguments

For endpoints that receive JSON (e.g., POST or PUT), simply annotate a function argument with your Pydantic model.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool = False

@app.post("/items/")
async def create_item(item: Item):
    # `item` is an instance of Item
    return {"item_name": item.name, "item_price": item.price}
  • Invalid JSON or wrong types trigger an automatic 422 Unprocessable Entity response.
  • The error body details exactly which fields failed validation.

Key Takeaways

  • Annotate your endpoint argument with the model to enable validation
  • Invalid input automatically returns a detailed error response

3. Controlling Responses with Response Models

3.1 Using the response_model Parameter

To expose only certain fields in the response, specify a different Pydantic model via response_model.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

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

class ItemOut(BaseModel):
    name: str
    price_with_tax: float

@app.post("/items/", response_model=ItemOut)
async def create_item(item: ItemIn):
    price_with_tax = item.price * 1.1
    return ItemOut(name=item.name, price_with_tax=price_with_tax)
  • You can omit internal fields for better security.
  • The auto-generated OpenAPI docs reflect ItemOut’s structure.

Key Takeaways

  • Declare response_model to shape your output
  • Unwanted fields are filtered out automatically

4. Advanced Field Configuration Techniques

4.1 Detailed Settings with Field

Use Pydantic’s Field function to add constraints and metadata.

from pydantic import BaseModel, Field

class User(BaseModel):
    id: int = Field(..., ge=1, description="User ID (integer ≥ 1)")
    name: str = Field(..., min_length=1, max_length=50)
    email: str = Field(..., regex=r'^\S+@\S+\.\S+$', description="Valid email address")
  • ... denotes a required field.
  • Validators like ge, le, min_length, max_length, regex cover many use cases.
  • description shows up in your OpenAPI docs.

4.2 Aliases and Input Shaping

When JSON keys don’t match your Python naming style, use alias.

class Product(BaseModel):
    product_id: int = Field(..., alias="id")
    product_name: str = Field(..., alias="name")

# Client sends {"id":1,"name":"Book"}
# Internally, use product_id and product_name attributes

Key Takeaways

  • Field adds constraints and doc annotations
  • alias separates JSON keys from property names

5. Nested Models, Lists, and Custom Validators

5.1 Nested Models

Pydantic makes it easy to nest models for complex structures.

class Address(BaseModel):
    street: str
    city: str

class UserProfile(BaseModel):
    name: str
    address: Address  # Nested model

@app.post("/profiles/")
async def create_profile(profile: UserProfile):
    return profile

5.2 List Fields

Accept multiple items by typing a list.

class Tag(BaseModel):
    name: str

class Article(BaseModel):
    title: str
    tags: list[Tag]  # List of Tag models

5.3 Custom Validators

For bespoke checks, use the @validator decorator.

from pydantic import validator

class Order(BaseModel):
    quantity: int

    @validator("quantity")
    def must_be_positive(cls, v):
        if v <= 0:
            raise ValueError("quantity must be positive")
        return v

Key Takeaways

  • Nesting and lists simplify complex schemas
  • @validator enables custom validation logic

6. Conclusion and Next Steps

This guide covered the essentials of defining request and response schemas with Pydantic in FastAPI:

  • Create models by inheriting from BaseModel
  • Apply them to requests and responses with minimal code
  • Use Field, alias, and validator for strict, flexible constraints
  • Model nesting and lists for real-world data shapes

Mastering these patterns lets you leverage FastAPI’s docs and type safety to build rock-solid APIs. Next up, combine these skills with database integration and authentication for fully featured services!

By greeden

Leave a Reply

Your email address will not be published. Required fields are marked *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)