原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。
pip install fastapi uvicorn
新建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}
方式一:命令启动
uvicorn main:app --reload
方式二:在mian.py中加启动代码
# mian.py
if __name__ == '__main__':
uvicorn.run(
app=app,
host="127.0.0.1",
port=5678
)
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.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
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
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)
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引入静态文件。
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
)
# 跨域配置
origins = [
"http://localhost:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
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
在 FastAPI 中使用 JWT 中间件,可以通过自定义 FastAPI 的中间件来实现。以下是在 FastAPI 中使用 JWT 中间件的步骤。
pip install PyJWT
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
SECRET_KEY = "mysecretkey" # 生产环境中应使用更复杂的密钥
ALGORITHM = "HS256" # 哈希算法
ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 访问令牌的过期时间,单位为分钟
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 异常。
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
类添加 CORSMiddleware
和 auth_middleware
中间件。auth_middleware
中间件将在每个路由处理函数执行前进行验证。因此,只需将路由的处理函数包装在 async def
函数中即可。
@app.get("/protected")
async def protected_route(request: Request):
current_user = request.state.user
return {"message": "Hello, {}".format(current_user)}
在以上示例中,使用 Request
类作为处理函数的一个参数,然后从请求的 state
属性中获取用户。
以上是使用 JWT 中间件的步骤,你可以根据项目的需求对上述代码进行进一步修改和优化。