FastAPI笔记

3月 21, 2023 · 2 分钟阅读时长

引入

介绍

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]
    

    在上述代码中,查询参数有skiplimit两个,在请求的时候可以通过如下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发送给客户端的数据。当我们需要使用请求体的时候,需要使用到PydanticBaseModel

  • 模型的创建

    一个基本的请求体设计如下所示

    # 导入基础的模型
    from pydantic import BaseModel
    
    # 声明模型以及其属性
    class Item(BaseModel):
        name: str
        description: Union[str, None] = None
        price: float
        tax: Union[float, None] = None
    

    上述模型有四个参数,可以看作一个JSON对象,其中descriptiontax是可选参数,也可以不进行提供

  • 模型的使用

    基础的使用方式就是接受一个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在两者都没有,因此上查询参数获得