Python-FastAPI入门

86 阅读5分钟

FastAPI介绍

FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.8+ 并基于标准的 Python 类型提示。

FastAPI 主要依赖:

官方文档: fastapi.tiangolo.com/zh/

源码github.com/tiangolo/fa…

fastapi、django、flask github热度对比

框架Star开源地址
django76.7kgithub.com/django/djan…
flask66.3Kgithub.com/pallets/fla…
fastapi70.9Kgithub.com/tiangolo/fa…

据长期观察,FastAPI start数量是增长速度最快的一个。

安装

pip install fastapi
#还会需要一个 ASGI 服务器
pip install "uvicorn[standard]"

可选依赖

用于 Pydantic:

用于 Starlette:

  • httpx - 使用 TestClient 时安装。
  • jinja2 - 使用默认模板配置时安装。
  • python-multipart - 需要通过 request.form() 对表单进行「解析」时安装。
  • itsdangerous - 需要 SessionMiddleware 支持时安装。
  • pyyaml - 使用 Starlette 提供的 SchemaGenerator 时安装(有 FastAPI 你可能并不需要它)。
  • graphene - 需要 GraphQLApp 支持时安装。

用于 FastAPI / Starlette:

  • uvicorn - 用于加载和运行你的应用程序的服务器。
  • orjson - 使用 ORJSONResponse 时安装。
  • ujson - 使用 UJSONResponse 时安装。

你可以通过 pip install "fastapi[all]" 命令来安装以上所有依赖。

start-demo

使用

  • 创建一个 main.py 文件并写入以下内容:
from typing import Union
# 1.导入 FastAPI
from fastapi import FastAPI
from pydantic import BaseModel

#2.创建一个 FastAPI
app = FastAPI()


class Item(BaseModel):
    name: str
    price: float
    is_offer: Union[bool, None] = None

# 创建路径操作
@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}


@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
    return {"item_name": item.name, "item_id": item_id}

启动

#启动命令
uvicorn main:app --reload
#看到这个说明正常启动
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

uvicorn main:app 命令含义如下:

  • main:main.py 文件(一个 Python「模块」)。
  • app:在 main.py 文件中通过 app = FastAPI() 创建的对象。
  • --reload:让服务器在更新代码后重新启动。仅在开发时使用该选项。

打开浏览器访问 http://127.0.0.1:8000

Api文档

swagger Ui 方式: http://127.0.0.1:8000/docs

redoc方式: http://127.0.0.1:8000/redoc

可以通过http://127.0.0.1:8000/openapi.json 查看项目的所有接口数据结构

使用指南

支持的路径操作

  • POST:创建数据
  • GET:读取数据
  • PUT:修改数据
  • DELETE:删除数据
  • OPTIONS
  • HEAD
  • PATCH
  • TRACE

可使用参数:

  • tags 用于添加标签;
  • status_code 用于响应中的 HTTP 状态码;
  • summary:接口概述;
  • description:接口详细描述
  • response_description:响应描述
  • deprecated:废弃接口

路径参数

from fastapi import FastAPI

app = FastAPI()

// me是user_id的一种
@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}

/users/{user_id}中的{user_id}就是路径参数

注意: 由于路径操作是按顺序依次运行的,因此,一定要在 /users/{user_id} 之前声明 /users/me。否则,/users/{user_id} 将匹配 /users/me,FastAPI 会认为正在接收值为 "me" 的 user_id 参数。

保安路径的路径参数:

@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"file_path": file_path}

/files/{file_path:path}中的file_path是一个路径参数,:path说明file_path应匹配路径

查询参数

from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]

访问:http://127.0.0.1:8000/items/?skip=0&limit=10

为不是路径参数的参数声明默认值,该参数就可选的了。

如果只想把参数设为可选,则要把默认值设为 None。

如果要把查询参数设置为必选,就不要声明默认值。

请求体

from fastapi import FastAPI
from pydantic import BaseModel


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


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item

与声明查询参数一样,包含默认值的模型属性是可选的,否则就是必选的。默认值为 None 的模型属性也是可选的。

参数描述和校验

这个如果使用过swagger的话,可以很好理解。这里值举个字符串的例子:

from typing import Union

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Union[str, None] = Query(
        default=None, #参数默认值,None标识可选,如果是必选,改为Required或...
        alias="item-query", #参数别名
        title="Query string", # 参数标题
        description="Query string",	#参数说明
        min_length=3, #字符串类型的数据长度校验
        max_length=50,#字符串类型的数据长度校验
        pattern="^fixedquery$", # 字符串类型正则匹配
        deprecated=True, #表明参数弃用
    ),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • Query 处理查询参数及校验
  • Path 处理路径参数及校验
  • Body:表明参数是请求体的一部分
  • Field:声明在模型上

响应模型

response_model 参数来定义响应模型

from typing import Any

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


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


@app.post("/items/", response_model=Item)
async def create_item(item: Item) -> Any:
    return item


@app.get("/items/", response_model=list[Item])
async def read_items() -> Any:
    return [
        {"name": "Portal Gun", "price": 42.0},
        {"name": "Plumbus", "price": 32.0},
    ]

请求文件

# 需要先安装
pip install python-multipart
from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File()):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}

File适合小型文件

UploadFile:更适于处理图像、视频、二进制文件等大型文件

错误处理

FastAPI 自带了一些默认异常处理器。触发 HTTPException 或请求无效数据时,这些处理器返回默认的 JSON 响应结果。不过,也可以使用自定义处理器覆盖默认异常处理器。

覆盖默认异常处理器时需要导入 RequestValidationError,并用 @app.excption_handler(RequestValidationError) 装饰异常处理器。

from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.responses import PlainTextResponse
from starlette.exceptions import HTTPException as StarletteHTTPException

app = FastAPI()


@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
    return PlainTextResponse(str(exc.detail), status_code=exc.status_code)


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=400)


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    if item_id == 3:
        raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
    return {"item_id": item_id}

FastAPI项目模板

全栈 FastAPI + PostgreSQL

github.com/tiangolo/fu…