Python FastAPI 快速入门

本教程介绍了 FastAPI 的基本使用,包括接口定义、数据模型、数据校验、依赖注入、中间件及接口文档。通过示例代码,展示了如何快速构建高性能 API 服务,适用于入门学习和实际开发。

GitHub:https://github.com/fastapi/fastapi
Document:https://fastapi.tiangolo.com/

conda create -n fastapi-env python=3.10
pip install uvicorn fastapi

1. 基本使用

这一部分讲解 FastAPI 的基本 API 定义方式,包括无参数、路径参数和请求参数的使用。

from fastapi import FastAPI
import uvicorn

# 初始化 api 应用
app = FastAPI()

# 1. 无参数
@app.post('/demo01')
async def demo01():
    return {'result': 100}

# 2. 路径参数
@app.post('/demo02/{param}')
async def demo02(param):
    return {'param': param}

# 3. 请求参数
@app.post('/demo03')
async def demo03(param):
    return {'param': param}


if __name__ == '__main__':
    # 使用 uvicorn 启动 api 应用
    uvicorn.run(app, host='127.0.0.1', port=8000)

2. 数据模型

这一部分介绍 Pydantic 数据模型的定义,并通过 response_model 指定返回数据格式。

import uvicorn
from pydantic import BaseModel
from fastapi import FastAPI

app = FastAPI()

class Request(BaseModel):
    name : str = 'undefined'
    age : int = 0


class Status(BaseModel):
    is_status1 : bool = False
    is_status2 : bool = False


class Response(BaseModel):
    grade: int
    score: int
    status : Status = {True, True}


# response_model 设置响应数据类型
@app.post('/demo', response_model=Response)
# request 设置传递进来的数据类型
async def demo(request : Request):
    return {'grade': 1001, 'score': 85, 'status': Status(is_status1=True, is_status2=False)}


if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000)

3. 数据校验

这一部分展示如何使用 Pydantic 的 Field 进行数据校验,包括字符串格式、数值范围及小数精度等。

import uvicorn
from pydantic import BaseModel
from pydantic import Field
from fastapi import FastAPI
from fastapi import Path
from fastapi import Query
from decimal import Decimal

app = FastAPI()

# 1. 请求和响应数据校验
class Data(BaseModel):
    # 字段默认指是undefined,最小长度2,最大长度10,必须满足前面是字母后面是数字的格式
    name : str = Field('undefined', min_length=2, max_length=10, pattern='^[a-zA-Z]+[0-9]+$')
    # 字段默认值是0,必须大于等于10,小于等于20,同时必须是2的倍数
    age : int = Field(0, ge=10, le=20, multiple_of=2)
    # 字段默认值是0.0,整个数字最大位数是5,小数部分位数是2,整数部分位数为3
    # 注意:Decimal 和 float 都是表示小数的类型,不同的是前者使用十进制方式进行存储,精度更好
    salary : Decimal = Field(0.0, max_digits=5, decimal_places=2)

@app.post('/demo01', response_model=Data)
async def demo01(data : Data):
    return data


# 2. 路径和请求参数校验
# path_param 为路径参数
# query_param 为请求参数
@app.post('/demo02/{path_param}')
# path_param 最小长度2,最大长度5,注意: Path 不可以设置默认值
# query_param 默认值 0,必须大于等于0并且小于20
async def demo02(path_param : str = Path(min_length=2, max_length=5),
                 query_param : int = Query(0, ge=0, lt=20)):
    return {'path_param': path_param, 'query_param': query_param}


if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000)

4. 依赖注入

这一部分讲解 FastAPI 依赖注入机制,包括全局依赖、局部依赖及多层依赖的使用。

依赖注入(Dependency Injection,简称 DI)是一种设计模式,它允许我们将对象的依赖关系从对象本身的创建和管理中分离出来。在 FastAPI 中,依赖注入用于将一些通用的逻辑(如身份验证、数据库连接等)封装到独立的函数中,然后在路径操作函数中使用这些依赖项。

from fastapi import FastAPI
from fastapi import Depends
import uvicorn

# 1. 全局依赖注入,每次请求都会执行依赖的可调用对象
def global_dependency1():
    print('全局依赖注入1')

def global_dependency2():
    print('全局依赖注入2')

app = FastAPI(dependencies=[Depends(global_dependency1), Depends(global_dependency2)])


# 2. 局部依赖注入,只有执行该请求时才会执行依赖可调用对象
# 2.1 函数作为依赖项
async def get_config():
    return {'c1': 10, 'c2': 20}

@app.post('/demo01')
async def demo01(param : dict = Depends(get_config)):
    return {'param': param}


# 2.2 类作为依赖项
class Config:
    def __init__(self):
        self.c1 = 10
        self.c2 = 20

@app.post('/demo02')
async def demo02(param : Config = Depends()):
    param.c1 = 100
    param.c2 = 200
    return {'param': param}


# 2.3 多层依赖项
async def get_dependency01():
    return {'c1': 1000, 'c2': 2000}

async def get_dependency02(param : dict = Depends(get_dependency01)):
    return param

@app.post('/demo03')
async def demo03(param : dict = Depends(get_dependency02)):
    return {'param': param}


if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000)

5. 中间件

这一部分介绍如何使用中间件拦截 HTTP 请求和响应,实现请求处理逻辑。当应用中存在多个中间件时,它们会按照注册的顺序依次执行。请求会先经过第一个中间件,然后依次经过后续的中间件,最后到达路径操作函数;响应则会按照相反的顺序经过各个中间件。

from fastapi import FastAPI
from fastapi import Request
from fastapi import Response
import uvicorn


app = FastAPI()


# 第一个中间件
@app.middleware('http')
async def middleware1(request: Request, call_next):
    print('middleware1:', request, call_next)
    response : Response = await call_next(request)
    print('middleware1:', response)
    return response


# 第二个中间件
@app.middleware('http')
async def middleware2(request: Request, call_next):
    print('middleware2:', request, call_next)
    response : Response = await call_next(request)
    print('middleware2:', response)
    return response


@app.post('/demo')
async def demo():
    return {'result': 'ok'}


if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000)

6. 接口文档

这一部分讲解如何配置 FastAPI 的 API 文档,包括全局信息、请求和响应参数说明及接口描述。启动 uvicorn 服务之后,可以:

  1. 通过 http://127.0.0.1:8000/docs 访问交互式文档
  2. 通过 http://127.0.0.1:8000/redoc 访问另外一种形式的文档

from fastapi import FastAPI
from fastapi import Query
from fastapi import Path
from pydantic import BaseModel
from pydantic import Field
import uvicorn


# 1. 定义全局文档信息
license_info={'name': 'Apache 2.0', 'url': 'https://www.apache.org/licenses/LICENSE-2.0.html'}
contact = {'name': 'Edward Meng', 'url': 'https://mengbaoliang.cn', 'email': 'chinapp@foxmail.com'}
terms_of_service = 'http://example.com/terms/'
app = FastAPI(title='接口文档',
              description='该接口提供了丰富的 LLM 访问接口.',
              version='1.0.0',
              redoc_url='/docs1',
              docs_url='/docs2',
              terms_of_service=terms_of_service,
              license_info=license_info,
              contact=contact)


# 2. 定义请求和响应参数文档信息
class MyRequest(BaseModel):
    name : str = Field(title='姓名', description='输入者的姓名')
    age : int = Field(title='年龄', description='输入者的年龄')

class MyResponse(BaseModel):
    grade: int = Field(title='等级', description='返回等级')
    score: int = Field(title='分数', description='返回分数')


# 3. 定义具体 api 文档信息
@app.post('/demo',
          summary='示例接口',
          description='我是对示例接口的描述',
          response_description='我是对接口返回值的描述',
          response_model=MyResponse)
async def demo(request : MyRequest):
    return {'grade': 1001, 'score': 85}


if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000)
未经允许不得转载:一亩三分地 » Python FastAPI 快速入门
评论 (1)

7 + 9 =

  1. avatar
    tcc04-19 22:28回复

    讲的真好