第三章 FastAPI v1.0
FastAPI是一个现代、快速(高性能)的Web框架,用于构建API,基于Python 3.7+类型提示
第一部分 基础入门
一、安装与环境
1.安装
bash
pip install fastapi uvicorn2.运行环境
- Python 3.7+
- Uvicorn(ASGI服务器)
二、第一个程序
python
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
if __name__ == "__main__":
uvicorn.run('main:app', host="127.0.0.1", port=8080, reload=True)三、路径参数
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}四、查询参数
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}第二部分 请求处理
一、请求体
python
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item二、表单参数
两种读取方式:File(读取为bytes)/UploadFile(读取为文件对象)
python
from fastapi import FastAPI, File, Form, UploadFile
app = FastAPI()
@app.post("/file")
async def test_file(file: bytes = File(), fileb: UploadFile = File()):
return {"filename": fileb.filename}三、查询参数与路径参数混合
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
user_id: int,
item_id: str,
q: str = None,
short: bool = False
):
item = {"item_id": item_id, "owner_id": user_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item第三部分 响应处理
一、响应模型
python
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
app = FastAPI()
@app.post("/items/", response_model=Item)
async def create_item(item: Item):
return item二、状态码
python
from fastapi import FastAPI, status
app = FastAPI()
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item():
return {"message": "Item created"}三、异常处理
python
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str):
if item_id not in items:
raise HTTPException(status_code=404, detail="Item not found")
return items[item_id]第四部分 高级特性
一、依赖注入
python
from fastapi import FastAPI, Depends
app = FastAPI()
async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons二、中间件
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# CORS中间件
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
allow_credentials=True,
)
# 自定义中间件
@app.middleware("http")
async def add_process_time_header(request, call_next):
import time
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三、安全与认证
python
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
app = FastAPI()
security = HTTPBearer()
async def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
if credentials.credentials != "secret_token":
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token"
)
return credentials.credentials
@app.get("/protected/")
async def protected_route(token: str = Depends(verify_token)):
return {"message": "Access granted", "token": token}第五部分 最佳实践
一、项目结构
my_fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── dependencies.py
│ ├── models/
│ │ ├── __init__.py
│ │ └── item.py
│ ├── routers/
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ └── schemas/
│ ├── __init__.py
│ └── item.py
├── requirements.txt
└── README.md二、路由组织
python
from fastapi import APIRouter
router = APIRouter(
prefix="/items",
tags=["items"],
responses={404: {"description": "Not found"}},
)
@router.get("/")
async def read_items():
return [{"name": "Item 1"}, {"name": "Item 2"}]
@router.get("/{item_id}")
async def read_item(item_id: int):
return {"name": "The Foo", "item_id": item_id}三、数据库集成
python
from fastapi import FastAPI
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
app = FastAPI()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()