【Fastapi框架】Fastapi的使用和进阶

原文作者 :我辈李想
版权声明 :文章原创,转载时请务必加上原文超链接、作者信息和本声明。


文章目录


前言


一、项目启动

1.安装

pip install fastapi  uvicorn

2.示例

新建main.py文件,

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@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}

3.启动

方式一:命令启动

uvicorn main:app --reload

方式二:在mian.py中加启动代码

# mian.py

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

4.路由

http://127.0.0.1:8000/

http://127.0.0.1:8000/items/1

http://127.0.0.1:8000/items/1?q=2

http://127.0.0.1:5678/docs#/

http://127.0.0.1:5678/redoc

二、进阶

1.请求数据

1.get请求:路径参数+查询参数

路由:http://127.0.0.1:8000/items/1?q=2,其中1是路径参数,q=2是查询参数。

@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}

2.post/put/delete请求:路径参数+请求体

路由:http://127.0.0.1:8000/items/1,其中1是路径参数,item是请求体。pydantic 可以验证输入和输出。

from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

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

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

3.嵌套数据

# 1.定义基础模型
class Image(BaseModel):
    url: str

# 2.赋给其他类属性
class Item(BaseModel):
    image: Union[Image, None] = None  # 单个
    images: Union[List[Image], None] = None  # 多个

4.文件上传

from fastapi import FastAPI, status, File, Form, UploadFile

app = FastAPI()

# 方法一:上传的文件会存在内存中,适合小型文件 
@app.post("/api/uploadFile/action")
async def create_file(file: Annotated[bytes, File()]):  
	writeBytes('./media',file)
	return {
        'code':200,
        "msg":'success'
    }

# 方法二:UploadFile
@app.post("/api/uploadFile/action")
async def create_upload_file(file: UploadFile):
	writeBytes('./media',file)
	return {
        'code':200,
        "msg":'success'
    }

# 上传多个文件
@app.post("/api/uploadFile/action")
async def create_upload_files(files: list[UploadFile]):
	writeBytes('./media',file)
	return {
        'code':200,
        "msg":'success'
    }
    
# 用 File() 添加额外设定
@app.post("/api/uploadFile/action")
async def create_upload_files(
    files: Annotated[
        list[UploadFile], File(description="Multiple files as UploadFile")
    ],
):
	writeBytes('./media',file)
	return {
        'code':200,
        "msg":'success'
    }
    
# 将file写入dirs目录文件
def writeBytes(dirs,file):
    bytesFile=file.file.read()
    filename=file.filename
    if not os.path.exists(dirs):
        os.makedirs(dirs)
    with open(dirs+'/'+ filename, "wb") as f:
        f.write(bytesFile)

5.数据校验

使用fastapi.params库中的函数,FastAPI会自动验证请求参数。Query,Bath 等。

from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(q: str = Query(None, min_length=3, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

6.request参数

@router.api_route("/test/{apiname}", methods=['GET', 'POST'])
async def test1(apiname, request: Request):
    args = await request.form()  # form数据
    args2 = await request.json()   # json数据
    print(apiname)
    print(request.method)
    return {'result': '这是一个GET或者POST'}

7.文档注释

@router.post('/roll-plan/kpi/', summary='获取输入数据', description='', tags=['算法'])
async def get_roll_plan(times: Annotated[RollPlanTimeItem, Body(examples=[{"start_time": "2023-12-12 00:00:00",
                                                                           "end_time": "2023-12-13 00:00:00"}],
                                                                )]
                        ):

8.请求体对象转json

python 复制代码
from datetime import datetime
from typing import Union

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    title: str
    timestamp: datetime
    description: Union[str, None] = None

@app.put("/items/{id}")
def update_item(id: str, item: Item):
    json_compatible_item_data = jsonable_encoder(item)
    # item.json()
    # item.dict()
    fake_db[id] = json_compatible_item_data

9.sqlalchemy查询数据转json

python 复制代码
roll_plans = session.query(rollPlan.AppRollPlanEntity).filter(
	rollPlan.AppRollPlanEntity.StartTime >= time_range[0],
	rollPlan.AppRollPlanEntity.StartTime <= time_range[1]).all()
	
# 方式一
item_data = [result[0].__dict__. for result in roll_plans]  # 将每个结果转换成字典形式
json_data = json.dumps(serialized_data)  # 将字典序列化为JSON字符串
# 方式二
from sqlalchemy.ext.serializer import loads, dumps
# 序列化
serialized_data = dumps(obj)

# 反序列化
deserialized_data = loads(serialized_data)
user = User(**deserialized_data)

2.静态文件加载

from fastapi import FastAPI
from starlette.staticfiles import StaticFiles

app = FastAPI()

# 静态文件配置使用mount挂载 第一个参数为应用的前缀,第二个为路径,第三个为别名
app.mount('/static', StaticFiles(directory='static'), name='static')

这里需要再main.py的同级目录创建static文件,在html文件中需要使用url_for引入静态文件。

<link rel="stylesheet" href="{{ url_for('static',path='demo.css') }}">

3.路由管理

1.在maipn.py的同级创建user文件夹,新建userRouter.py文件

from typing import Union

from fastapi import FastAPI, APIRouter, Request

router = APIRouter(prefix='/bp', tags=['bp'])

@router.get('/')
def read_root():
    return {"Hello": "World"}

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


# @router.get('/test/{apiname}')
# @router.post("/test/{apiname}")
@router.api_route("/test/{apiname}", methods=['GET', 'POST'])
async def test1(apiname, request: Request):
	args = await request.form()
    print(apiname)
    print(request.method)
    return {'result': '这是一个GET或者POST'}

2.修改mapin.py内容

from fastapi import FastAPI
from user import userRouter 

app = FastAPI()
app.include_router(userRouter.router)

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

4.跨域配置

# 跨域配置
origins = [
    "http://localhost:3000",
]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

5.自定义中间件

1.已有中间件

HTTPSRedirectMiddleware是fasapi自带的中间件

app.add_middleware(HTTPSRedirectMiddleware)
app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["tigeriaf.com", "*.tigeriaf.com"]
)

2.自定义中间件

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

6.使用jwt中间件

在 FastAPI 中使用 JWT 中间件,可以通过自定义 FastAPI 的中间件来实现。以下是在 FastAPI 中使用 JWT 中间件的步骤。

  1. 安装 PyJWT。
python 复制代码
pip install PyJWT
  1. 导入 PyJWT 库和 FastAPI 组件。
python 复制代码
import jwt
from fastapi import FastAPI, HTTPException
from fastapi.middleware import Middleware
from fastapi.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.status import HTTP_401_UNAUTHORIZED
  1. 定义一些全局变量,例如:
python 复制代码
SECRET_KEY = "mysecretkey"  # 生产环境中应使用更复杂的密钥
ALGORITHM = "HS256"  # 哈希算法
ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 访问令牌的过期时间,单位为分钟
  1. 定义 JWT 认证的中间件函数。
python 复制代码
async def auth_middleware(request: Request, call_next):
    try:
        token: str = request.headers["Authorization"].split()[1]
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise HTTPException(status_code=HTTP_401_UNAUTHORIZED, detail="Invalid authentication credentials")
        request.state.user = username
    except (KeyError, IndexError, jwt.JWTError):
        raise HTTPException(status_code=HTTP_401_UNAUTHORIZED, detail="Invalid authentication credentials")
    response = await call_next(request)
    return response

auth_middleware 函数获取请求头中的访问令牌,并解码 JWT。如果 JWT 解码成功,则将用户名添加到请求对象的 state 属性中。如果 JWT 解码失败,则抛出 HTTPException 异常。

  1. 在 FastAPI 中添加中间件。
python 复制代码
middleware = [
    Middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]),
    Middleware(auth_middleware)
]

app = FastAPI(
    title="My API",
    openapi_url="/api/v1/openapi.json",
    docs_url="/api/v1/docs",
    redoc_url=None,
    middleware=middleware
)

在 FastAPI 的构造函数中,使用 Middleware 类添加 CORSMiddlewareauth_middleware 中间件。auth_middleware 中间件将在每个路由处理函数执行前进行验证。因此,只需将路由的处理函数包装在 async def 函数中即可。

python 复制代码
@app.get("/protected")
async def protected_route(request: Request):
    current_user = request.state.user
    return {"message": "Hello, {}".format(current_user)}

在以上示例中,使用 Request 类作为处理函数的一个参数,然后从请求的 state 属性中获取用户。

以上是使用 JWT 中间件的步骤,你可以根据项目的需求对上述代码进行进一步修改和优化。

相关推荐
指弹代码摄影狗1 小时前
【Fastapi】参数获取,json和query
python·fastapi
用户673559885612 天前
数据驱动,实时监控显威力 —— 淘宝商品详情API助力商家精准营销
后端·api·fastapi
_.Switch2 天前
Python Web 开发中的性能优化策略(一)
开发语言·前端·python·性能优化·django·flask·fastapi
黑金IT7 天前
WebSocket vs. Server-Sent Events:选择最适合你的实时数据流技术
网络·python·websocket·网络协议·fastapi
黑金IT7 天前
FastAPI 应用安全加固:HTTPSRedirectMiddleware 中间件全解析
安全·中间件·fastapi
写bug如流水8 天前
【FastAPI】实现服务器向客户端发送SSE(Server-Sent Events)广播
服务器·python·fastapi
黑金IT8 天前
从单体到微服务:FastAPI ‘挂载’子应用程序的转变
微服务·架构·fastapi
不良人龍木木9 天前
sqlalchemy FastAPI 前端实现数据库增删改查
前端·数据库·fastapi
写bug如流水9 天前
【FastAPI】离线使用Swagger UI 或 国内网络如何快速加载Swagger UI
ui·fastapi·命令模式
布响哒公11 天前
用python fastapi写一个http接口,使ros2机器人开始slam toolbox建图
python·机器人·fastapi