这篇文章上次修改于 795 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
There are severl forms of parameter in FastAPI such as Path, Query and so on, we are going to introduce some basic parameter we may frequently use.
Path
To use a path parameter, add a {[PARAM_NAME]} in the path in router decorator like below:
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")],
):
passIn example above, item_id will become a path parameter.
Notice: Path parameter could NEVER be None, that means you always need to pass a path parameter.
Specified Path
Keep using the example above, imagine we not only have items/id form, but we also want to add a items/stat endpoint which provide another different info such as items current statistics, how to do it?
Here we should know, the priority of the endpoint is determined by their appearance order in the code. So what should we do is to add a items/stat before we declare the previous items/{item_id} function. Below is code example:
@app.get("/items/stat")
async def read_items():
# do sth here
pass
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")],
):
passWith code above, when we access item/stat, the request will be handled by the first function.
Query
Based on official docs of FastAPI, if the function parameter is not a path parameter, then it would be considered as a query parameter, like code below:
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]In example above, skip and limit are both be considered a query parameter.
Add metadata
To set more limit and add more detail to a query parameter, you can use Python type anno system with Annotated[].
(Notice: Annotated seems to be a new function which just get supported by FastAPI recently, be sure your FastAPI is the newer version if you want to use this feature)
For example, if you want to limit the maximum length of a query parameter, you can write some code like below:
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
# do sthIn example above, we use Annotated and Query to set the max_length limit of param q.
By doing this, FastAPI will:
- Validate the param
- Provide full auto-documentation support about those limit
Make Query Required
Basically there are 2 method to make a query param to be required.
First (and maybe the most used way) is quite simple -- just do not set a default value. A query param with no default value will be automatically considered as required.
Alternatively, you can use ... (Ellipsis) grammer to explicitly mark a query param as required like below:
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
# do sthRequired but allow None
This may have a extremely rare situation, that you need to set a param required, but you accept a None value of this param. Than you can use explicit require mark with Nont type, like below:
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(min_length=3)] = ...):
# do sthDefault Value for Query Param
Notice, here we don't use Query(default=None, ...) to set the default value to None, but use the Python style default value. This pattern is recommended in the latest FastAPI doc, for more info please check Advantages of Annotated
Request Body
If you want to get a specified request body from a request, then you may need to declare a class inherited from pydantic.BaseModel, and use it in your function declaration, like below:
class Item(BaseModel):
name: str
description: str | None = None
@app.post("/items/{item_id}")
async def update_item(
item: Item | None = None,
):
# do sthBy doing above, FastAPI now will automatically validate the request body, and you can access the data in request body by item param.
Multiple Body
In case above, we only received one body object called item, we can actually add more than one body param to the function like below:
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User):
# do sthIn above cases, FastAPI will know that you are expecting more than one part of body, and the JSON with pattern below is expected when you send request:
{
"item": {
"name": "Foo",
"description": "The pretender",
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
}
}Body with single value
Above, we add a custom class inherited from pydantic.BaseModel to indicate a param as a body param.
But like Query() and Path(), we are able to use Body() provided by FastAPI to set some extra info for a body param, or explicitly mark a param as a body param. See example below:
@app.post()
def update_item(update_if_exist: Annotated[bool, Body()]):
# do sthThe code above explicitly set update_if_exist to be a bool value in request body, and a JSON with pattern below is expected:
{
"update_if_exist": true
}Notice: If you don't explicitly set the param type, then a single value will be consider as a query param.Cookies & Headers
Using Cookie() & Header()
To get cookies and headers from a request, you can use Cookie() and Header() provided by FastAPI. Here is the code example:
from typing import Annotated
from fastapi import Cookie, FastAPI
@app.get("/items/")
async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
# do sthBy add the Cookie() in the type anno, you tell FastAPI that ads_id here is a cookie param.
FastAPI will look over the received Request object's cookies dict, and auto validate the ads_id param if there has a ads_id in the cookies of this request.
The method of getting a specific header is same as you do with cookies, here we don't provide the example again.
Check Official Doc for more info.
Directly Access Request
Thing to know first, FastAPI is built with some other packages like pydantic and starlette. FastAPI allows us to access Request which provided by the Starlette package, and provide a wrap to the starlette API, check example below:
from fastapi import FastAPI, Request
@app.get("/items/{item_id}")
def read_root(item_id: str, request: Request):
# do sth, access request param hereCookies and Headers now can be acccessed through this request param.
Based on lastest Starlette doc, you can use request.cookies and request.headers to access them. To be simple, you can consider them as a dict.
For more info about class member in Request, check Starlette Request Reference
没有评论