FastAPI Response Model

Response models are used to declare the data structure returned by the API. By declaring a response model, FastAPI automatically handles validation, serialization, and filtering of output data, ensuring that the client only receives the expected data.


Using return type annotations

The simplest way is to directly annotate the return type of the path operation function:

Example

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int):
    # The returned data will be automatically filtered and validated according to the Item model
    return {
        "name": "Foo",
        "description": "A very nice Item",
        "price": 22.2,
        "secret": "this should not be visible",  # Fields not in Item will be filtered
    }

FastAPI uses the response model to accomplish the following:

FeaturesDescription
Data verificationIf the returned data does not match the model, it indicates a problem with the application code.
Data filteringOnly return the fields defined in the model, filtering out extra fields (this is important for security).
Generate documentationDisplay the response structure in the OpenAPI documentation.
serializationUse Pydantic (Rust implementation) to efficiently convert data to JSON.

response_model parameter

When the return type is inconsistent with the response model, use the decorator'sresponse_modelParameters:

Example

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


# Input model (contains password)
class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr


# Output model (without password)
class UserOut(BaseModel):
    username: str
    email: EmailStr


# Function receives UserIn, but response uses UserOut
@app.post("/users/", response_model=UserOut)
async def create_user(user: UserIn):
    # The returned user contains the password, but response_model=UserOut will filter out the password.
    return user

This is an important way to protect sensitive data. By using different input and output models, sensitive fields such as passwords never appear in API responses.


Return type and data filtering

RecommendedClassInheritancecomeImplementationInput/OutputModelofDivide离,这sample既abilityLetEditorand mypy Correct understandingType,又abilityLet FastAPI FilterData:

Example

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


# Basic User Model
class BaseUser(BaseModel):
    username: str
    email: EmailStr


# Input model: inherits base model, adds password field
class UserIn(BaseUser):
    password: str


@app.post("/users/")
async def create_user(user: UserIn) -> BaseUser:
    # The return type annotation is BaseUser, and FastAPI will filter out the password field.
    # The editor and mypy are also satisfied, because UserIn is a subclass of BaseUser
    return user

Excluding unset default values

Usageresponse_model_exclude_unset=True, only return fields that actually have values set:

Example

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
    return items[item_id]

Comparison of responses for different item_id:

item_idresponseDescription
foo{"name": "Foo", "price": 50.2}Only explicitly set fields are returned, omitting default values.
bar{"name": "Bar", "description": "...", "price": 62, "tax": 20.2}All fields have actual values, so all are returned

Related filter parameters:

ParameterDescription
response_model_exclude_unsetExclude fields with unset values
response_model_exclude_defaultsExclude fields with default values
response_model_exclude_noneExclude fields with value None

Include/exclude specific fields

Usageresponse_model_includeandresponse_model_excludePrecisely control output fields:

Example

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float = 10.5


# Only contains name and description
@app.get("/items/{item_id}", response_model=Item, response_model_include={"name", "description"})
async def read_item_name(item_id: str):
    return items[item_id]


# Exclude Tax
@app.get("/items/{item_id}/no-tax", response_model=Item, response_model_exclude={"tax"})
async def read_item_no_tax(item_id: str):
    return items[item_id]

Althoughresponse_model_includeandresponse_model_excludeCan quickly filter fields, but it is recommended to use multiple model classes instead, because they cannot remove the excluded fields from the OpenAPI documentation.


Summary

  • Usageresponse_modelParameter or return type annotations declare the response model.
  • The core role of the response model is data filtering, protecting sensitive data from being leaked.
  • Use different models for input and output to ensure that fields such as passwords do not appear in the response.
  • response_model_exclude_unsetOnly return fields that are actually set
  • It is recommended to use model inheritance + return type annotations rather thanresponse_model_include/exclude
other extensions