FastAPI笔记
引入
介绍
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。
安装
完整安装:pip install "fastapi[all]"
,这种安装方式包括了unicorn
部分安装:pip install fastapi
服务的启动
一个最简单的FastAPI如下所示:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
需要将这个文件所描述的服务进行启动可以使用命令:uvicorn main:app --reload
,最后一个reload
表示是在更新代码后重新启动
接口文档
这个框架会基于openapi自动生成文档,原始的文件在/openai.json
中,在/docs
和/redoc
中可以分别看到两个不同显示界面的文档
基础使用
参数
-
路径参数
在URL的路径中,可以加入部分的参数提供给处理的函数,一个基本的例子如下
@app.get("/items/{item_id}") async def read_item(item_id: int): return {"item_id": item_id}
其中
{item_id}
就是路径参数,在函数的参数列表中被读取并设置了类型int
,这一类型设置会自动转换/检测路径中提供的参数是否符合需求,若不符合则会直接进行报错。在使用路径参数的时候需要注意到其前后顺序,顺序会代表相应的优先级,一般固定内容的处理会放在参数内容的处理之前(如下)
# 先放置me这一固定的部分 @app.get("/users/me") async def read_user_me(): return {"user_id": "the current user"} @app.get("/users/{user_id}") async def read_user(user_id: str): return {"user_id": user_id}
当我们希望路径参数是一个可选类型的时候,可以使用python中的Enum枚举类型来实现
from enum import Enum ... class ModelName(str, Enum): #str限制类型为字符串,继承枚举则转变为枚举类型 alexnet = "alexnet" resnet = "resnet" lenet = "lenet" @app.get("/models/{model_name}") async def get_model(model_name: ModelName): # 此处的标记将自动将路径参数转换为枚举 ...
对于路径参数的数值校验可以使用
Path
类型,其具体使用与之后的Query
基本类似,如下代码进行演示@app.get("/items/{item_id}") async def read_items(q: str, item_id: int = Path(title="The ID of the item to get", gt=0, le=1000,# 大于0,小于1000 )): results = {"item_id": item_id} if q: results.update({"q": q}) return results
-
查询参数
当在函数的参数中声明不属于路径参数的其他参数的时候,会被解释为查询参数
@app.get("/items/") async def read_item(skip: int = 0, limit: int = 10): return fake_items_db[skip : skip + limit]
在上述代码中,查询参数有
skip
与limit
两个,在请求的时候可以通过如下URL进行请求http://127.0.0.1:8000/items/?skip=0&limit=10
对于这一类型的参数,一般会提供默认值,或者使用
None
来声明,将其变化为可选参数。若不提供任何默认值,则在请求的时候必须提供这一参数,否则会报错。路径参数与查询参数使用名称进行检测,可以以任特定的顺序来进行声明
除了一些基础的校验外,有时候需要为查询参数加入更多的校验(例如字符串长度),可以使用
Query
来进行实现from fastapi import FastAPI, Query @app.get("/items/") async def read_items(q: Union[str, None] = Query(default=None, #设置默认值 title="Query string", # 设置参数名字 description="Query string", # 设置参数描述 min_length=3, #设置最小长度 max_length=50, # 设置最大长度 regex="^fixedquery$", #设置正则表达式 eprecated=False, # 设置为弃用参数 alias="item-query")): # 设置参数别名 results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) return results
在上述的代码中,使用
Query
来对于参数进行校验以及默认值设置,当我们想要将其转变为必选参数的时候,则需要以from pydantic import Required
中的Required
作为默认值
请求体
当数据需要从客户端发送API的时候,通常作为请求体进行发送。请求体是客户端发送给API的数据,响应体是API发送给客户端的数据。当我们需要使用请求体的时候,需要使用到Pydantic
的BaseModel
。
-
模型的创建
一个基本的请求体设计如下所示
# 导入基础的模型 from pydantic import BaseModel # 声明模型以及其属性 class Item(BaseModel): name: str description: Union[str, None] = None price: float tax: Union[float, None] = None
上述模型有四个参数,可以看作一个
JSON
对象,其中description
和tax
是可选参数,也可以不进行提供 -
模型的使用
基础的使用方式就是接受一个
post
提供的json,如下@app.post("/items/") async def create_item(item: Item): item_dict = item.dict() #直接转化为字典进行使用 return item
通常的情况下,我们会接收到请求体、路径参数、查询参数三个部分,例如下面的情况
@app.put("/items/{item_id}") async def create_item(item_id: int, item: Item, q: Union[str, None] = None): result = {"item_id": item_id, **item.dict()} if q: result.update({"q": q}) return result
item_id
根据路径参数获得,item
在请求体中获得、q
在两者都没有,因此上查询参数获得