Fastapi 迁移模型、token 认证、中间件、CORS、后台任务、测试用例
alembic 迁移模型
pip install alembic=1.13.1
初始化Alembic 项目
alembic init alembic
会生成alebic.ini文件 修改里面的数据库连接
[alembic] script_location = alembic sqlalchemy.url = mysql+pymysql://david:123456@localhost/summary [loggers] keys = root [handlers] keys = console [formatters] keys = generic [logger_root] level = WARN handlers = console qualname = [handler_console] class = StreamHandler args = (sys.stderr,) level = NOTSET formatter = generic [formatter_generic] format = %(levelname)-5.5s [%(name)s] %(message)s
alembic/env.py,修改meatadata中的信息,是target_matadata指向项目中真实的路径
from models import Base target_metadata = Base.metadata
创建一个表,生成迁移文件
alembic revision --autogenerate -m "create_user_table"
执行迁移
alembic upgrade head
后续添加字段只需重复执行下面的两条命令即可
alembic revision --autogenerate -m "add phone field to user" alembic upgrade head
用户认证
from fastapi import FastAPI, Security, HTTPException
from fastapi.security import APIKeyHeader
app = FastAPI()
api_key = APIKeyHeader(name="api_key")
@app.get("/protected")
async def protected_route(api_key: str = Security(api_key)):
if api_key != "your_api_key":
raise HTTPException(status_code=401, detail="Invalid API key")
return current_user
常用中间件
from fastapi.middleware.cors import CORSMiddleware
@app.middleware('http')
async def add_process_time_header(request: Request, call_next): # call_next将接收request请求做为参数
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers['X-Process-Time'] = str(process_time) # 添加自定义的以“X-”开头的请求头
return response
app.add_middleware(
CORSMiddleware,
allow_origins=[
"*"
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
实现类似celery 的后台任务
BackgroundTasks 开启后台任务
from typing import Optional
from fastapi import APIRouter, BackgroundTasks, Depends
app08 = APIRouter()
def bg_task(framework: str):
with open("README.md", mode="a") as f:
f.write(f"test")
@app08.post("/background_tasks")
async def run_bg_task(framework: str, background_tasks: BackgroundTasks):
"""
:param framework: 被调用的后台任务函数的参数
:param background_tasks: FastAPI.BackgroundTasks
:return:
"""
background_tasks.add_task(bg_task, framework)
return {"message": "任务已在后台运行"}
引入其他的BackgroundTasks
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# __author__ = '__Jack__'
from typing import Optional
from fastapi import APIRouter, BackgroundTasks, Depends
app08 = APIRouter()
"""Background Tasks 后台任务"""
def bg_task(framework: str):
with open("README.md", mode="a") as f:
f.write(f"test")
def continue_write_readme(background_tasks: BackgroundTasks, q: Optional[str] = None):
if q:
background_tasks.add_task(bg_task, "\n> 整体的介绍 FastAPI,快速上手开发,结合 API 交互文档逐个讲解核心模块的使用\n")
return q
@app08.post("/dependency/background_tasks")
async def dependency_run_bg_task(q: str = Depends(continue_write_readme)):
if q:
return {"message": "README.md更新成功"}
需要注意的点,不要在后台任务中使用depends
def bg_task(url: HttpUrl, db: Session):
"""这里注意一个坑,不要在后台任务的参数中db: Session = Depends(get_db)这样导入依赖"""
编写单元测试用例
#!/usr/bin/python3
# -*- coding:utf-8 -*-
# __author__ = '__Jack__'
from fastapi.testclient import TestClient
from run import app
"""Testing 测试用例"""
client = TestClient(app) # 先pip install pytest
def test_run_bg_task(): # 函数名用“test_”开头是 pytest 的规范。注意不是async def
response = client.post(url="/chapter08/background_tasks?framework=FastAPI")
assert response.status_code == 200
assert response.json() == {"message": "任务已在后台运行"}
def test_dependency_run_bg_task():
response = client.post(url="/chapter08/dependency/background_tasks")
assert response.status_code == 200
assert response.json() is None
def test_dependency_run_bg_task_q():
response = client.post(url="/chapter08/dependency/background_tasks?q=1")
assert response.status_code == 200
assert response.json() == {"message": "README.md更新成功"}

浙公网安备 33010602011771号