This blog was last modified 554 days before.
Why using Response Model
There are several reasons that we should use Response Model patterns provided by FastAPI.
- Validate Response Data
With Response Model set, FastAPI will automatically check and validate the function return object, ensuring you are returning info with right type to your client.
- Filter Unwanted Data (Important to security)
FastAPI will only returns the data that match the Response Model, with allows you to control what info could be returned to the client.
class SomeInfo(BaseModel):
not_important_data: str
safety_key: str
class ReturnInfo(BaseModel):
not_important_data: str
@app.get(response_model=ReturnInfo)
def return_info():
# do sth
return SomeInfo()
For example, in code above, safety_key
will NOT appeared in the respone on client, since which didn't appeared in the respone model: ReturnInfo
.
Set Response Model
There are two different way to set response model, we recommend using the second one, reason will be explained later at below.
Using Python Function Return Type Anno
The simplest way to set a Response Model is using the function return type anno grammer provided by Python like below:
@app.post("/items/")
async def create_item(item: Item) -> Item:
return item
In code above, Item
has been set as the Response Model
response_model
param in Router Decorator
Using Here is another approach:
@app.get("/items/", response_model=list[Item])
async def read_items() -> Any:
return [
{"name": "Portal Gun", "price": 42.0},
{"name": "Plumbus", "price": 32.0},
]
In this case, we set Response Model in router decorator, and this also works as intend.
Why Second Approach is Recommend
Sometimes we may meet the situation that the return object is not exactly the type same as the response type.
For example, we want to respone a database object retrive from database, but for safety reason (explain in beginning of this passage), we create a custom class called ReturnUserInfo
, and in which some sensitive field has been removed.
If now we used the first method to set the response type, then when we want to directly return the database object (which is not the type of ReturnUserInfo
), then Python will complain that the return type is wrong. And the same issue will not appear if we use the second approach.
Tips About Creating Model Classes
We have already learn how to specify a response model class for FastAPI.
Here is some tips we may used when writing a model class for FastAPI.
Factory Constructor with Pydantic
Pydantic
has its own overrided __init__()
method, and it's NOT recommend to override the init method of a subclass of pydantic.BaseModel
.
We could use Python @classmethod
decorator to implement Factory Constructor pattern. Here is example:
class ServerPingInfo(BaseModel):
"""
Response model of server ping api
"""
# this could be float on some supported platform (based on time() comment)
server_time: float
@classmethod
def from_request(cls, req: Request) -> "ServerPingInfo":
info = cls(server_time=time())
return info
In example above, we use @classmethod
to create a factory constructor from_request()
, which could create a ServerPingInfo
class instance based on a req
info.
Notice the trick we used in the return type anno of this function. We need to add the quote "
of the return type, since the return type is this class itself.
More info about Python @classmethod and @staticmethod
No comment