使用FastAPI构建高性能RESTfulAPI的完整指南

Written by

in

文章目录
  • FastAPI是一个现代、高性能的Python Web框架,专为构建API而设计。它基于标准的Python类型提示,提供了自动的API文档生成、数据验证和序列化等强大功能。本指南将带你从基础到高级,全面掌握FastAPI的使用。
  • FastAPI相比其他框架有以下显著优势: 高性能: 性能可与NodeJS和Go媲美,是最快的Python框架之一 开发效率高: 比传统框架减少约40%的开发时间 自动文档: 自动生成交互式API文档(Swagger UI和ReDoc) 类型安全: 基于Python类型提示,提供编辑器自动补全和类型检查 标准化: 基于OpenAPI和JSON Schema标准 异步支持: 原生支持async/await语法
  • SQLAlchemy集成 from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = “sqlite:///./test.db” engine = create_engine(SQLALCHEMY_DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class User(Base): __tablename__ = “users” id = Column(Integer, primary_key=True, index=True) email = Column(String, unique=True, index=True) name = Column(String) Base.metadata.create_all(bind=engine) @app.post(“/users/”) def create_user(user: UserCreate, db: Session = Depends(get_db)): db_user = User(**user.dict()) db.add(db_user) db.commit() db.refresh(db_user) return db_user
  • from fastapi import BackgroundTasks def write_log(message: str): with open(“log.txt”, mode=”a”) as log: log.write(message + “n”) @app.post(“/send-notification/”) async def send_notification( email: str, background_tasks: BackgroundTasks ): background_tasks.add_task(write_log, f”通知发送到: {email}”) return {“message”: “通知将在后台发送”}
  • 使用TestClient from fastapi.testclient import TestClient client = TestClient(app) def test_read_main(): response = client.get(“/”) assert response.status_code == 200 assert response.json() == {“message”: “Hello World”} def test_create_item(): response = client.post( “/items/”, json={“name”: “测试商品”, “price”: 99.99} ) assert response.status_code == 201 assert response.json()[“name”] == “测试商品”
  • FastAPI是一个强大而现代的Python Web框架,它结合了高性能、开发效率和优秀的开发者体验。通过本指南,你已经学习了: FastAPI的核心概念和基础用法 数据验证和序列化 依赖注入系统 认证和授权 数据库集成 性能优化技巧 生产环境部署 继续深入学习FastAPI的官方文档,并在实际项目中应用这些知识,你将能够构建出高性能、可维护的RESTful API应用。 以上就是使用FastAPI构建高性能RESTful API的完整指南的详细内容,更多关于FastAPI构建高性能API的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: python基于FastAPI实现一个简易的在线用户统计功能 Python如何使用FastAPI玩转文件上传功能 Python FastAPI入门安装使用 python如何通过FastAPI构建复杂的Web API Python 框架 FastAPI详解 Python 搭建 FastAPI 项目的详细过程
  • 目录
    • 引言
    • 为什么选择FastAPI
    • 环境搭建
      • 安装依赖
      • 第一个API应用
    • 核心概念
      • 路径参数
      • 查询参数
      • 请求体
    • 数据验证
      • 使用Field进行高级验证
      • 使用Query、Path和Body
    • 响应模型
      • 定义响应结构
      • 多种响应状态码
    • 错误处理
      • 抛出HTTP异常
      • 自定义异常处理器
    • 依赖注入
      • 基础依赖
      • 类作为依赖
      • 数据库会话依赖
    • 认证和授权
      • JWT认证示例
      • OAuth2密码流
    • 数据库集成
      • 中间件
        • 添加CORS中间件
        • 自定义中间件
      • 后台任务
        • 文件上传和下载
          • 文件上传
          • 多文件上传
        • 测试
          • 性能优化
            • 使用异步操作
            • 数据库查询优化
            • 响应缓存
          • 部署
            • 使用Docker
            • 生产环境配置
            • 环境变量配置
          • 最佳实践
            • 项目结构
            • 使用APIRouter组织路由
            • 版本控制
          • 总结

            FastAPI是一个现代、高性能的Python Web框架,专为构建API而设计。它基于标准的Python类型提示,提供了自动的API文档生成、数据验证和序列化等强大功能。本指南将带你从基础到高级,全面掌握FastAPI的使用。

            FastAPI相比其他框架有以下显著优势:

            • 高性能: 性能可与NodeJS和Go媲美,是最快的Python框架之一
            • 开发效率高: 比传统框架减少约40%的开发时间
            • 自动文档: 自动生成交互式API文档(Swagger UI和ReDoc)
            • 类型安全: 基于Python类型提示,提供编辑器自动补全和类型检查
            • 标准化: 基于OpenAPI和JSON Schema标准
            • 异步支持: 原生支持async/await语法

            # 创建虚拟环境
            python -m venv venv
            source venv/bin/activate  # Windows: venvScriptsactivate
            
            # 安装FastAPI和ASGI服务器
            pip install fastapi
            pip install "uvicorn[standard]"
            

            创建main.py文件:

            from fastapi import FastAPI
            
            app = FastAPI()
            
            @app.get("/")
            async def root():
                return {"message": "Hello World"}
            

            运行应用:

            uvicorn main:app --reload
            

            访问http://localhost:8000即可看到返回结果,访问http://localhost:8000/docs可以看到自动生成的交互式文档。

            @app.get("/items/{item_id}")
            async def read_item(item_id: int):
                return {"item_id": item_id}
            

            FastAPI会自动进行类型转换和验证,如果item_id不是整数,会返回清晰的错误信息。

            @app.get("/items/")
            async def read_items(skip: int = 0, limit: int = 10):
                return {"skip": skip, "limit": limit}
            

            查询参数在URL中以?skip=0&limit=10的形式传递。

            使用Pydantic模型定义请求体:

            from pydantic import BaseModel
            
            class Item(BaseModel):
                name: str
                description: str | None = None
                price: float
                tax: float | None = None
            
            @app.post("/items/")
            async def create_item(item: Item):
                return item
            

            Pydantic会自动验证请求数据,并提供清晰的错误提示。

            from pydantic import BaseModel, Field
            
            class Item(BaseModel):
                name: str = Field(..., min_length=1, max_length=100)
                price: float = Field(..., gt=0, description="价格必须大于0")
                quantity: int = Field(default=1, ge=1, le=1000)
                tags: list[str] = Field(default_factory=list)
            

            from fastapi import Query, Path, Body
            
            @app.get("/items/{item_id}")
            async def read_item(
                item_id: int = Path(..., title="商品ID", ge=1),
                q: str | None = Query(None, min_length=3, max_length=50),
                size: int = Query(default=10, le=100)
            ):
                return {"item_id": item_id, "q": q, "size": size}
            

            class ItemResponse(BaseModel):
                id: int
                name: str
                price: float
                
                class Config:
                    from_attributes = True
            
            @app.post("/items/", response_model=ItemResponse)
            async def create_item(item: Item):
                # 假设保存到数据库后返回
                return {"id": 1, **item.dict()}
            

            from fastapi import status
            
            @app.post("/items/", status_code=status.HTTP_201_CREATED)
            async def create_item(item: Item):
                return item
            
            @app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
            async def delete_item(item_id: int):
                return None
            

            from fastapi import HTTPException
            
            @app.get("/items/{item_id}")
            async def read_item(item_id: int):
                if item_id not in items_db:
                    raise HTTPException(
                        status_code=404,
                        detail="商品未找到",
                        headers={"X-Error": "Item not found"}
                    )
                return items_db[item_id]
            

            from fastapi.responses import JSONResponse
            from fastapi import Request
            
            class CustomException(Exception):
                def __init__(self, name: str):
                    self.name = name
            
            @app.exception_handler(CustomException)
            async def custom_exception_handler(request: Request, exc: CustomException):
                return JSONResponse(
                    status_code=418,
                    content={"message": f"处理 {exc.name} 时出错"}
                )
            

            from fastapi import Depends
            
            async def common_parameters(q: str | None = 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
            

            class Pagination:
                def __init__(self, skip: int = 0, limit: int = 100):
                    self.skip = skip
                    self.limit = limit
            
            @app.get("/users/")
            async def read_users(pagination: Pagination = Depends()):
                return {"skip": pagination.skip, "limit": pagination.limit}
            

            from sqlalchemy.orm import Session
            
            def get_db():
                db = SessionLocal()
                try:
                    yield db
                finally:
                    db.close()
            
            @app.get("/users/")
            async def read_users(db: Session = Depends(get_db)):
                users = db.query(User).all()
                return users
            

            from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
            from fastapi import Security
            import jwt
            
            security = HTTPBearer()
            
            def verify_token(credentials: HTTPAuthorizationCredentials = Security(security)):
                token = credentials.credentials
                try:
                    payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
                    return payload
                except jwt.InvalidTokenError:
                    raise HTTPException(status_code=401, detail="无效的token")
            
            @app.get("/protected/")
            async def protected_route(payload: dict = Depends(verify_token)):
                return {"user": payload["sub"]}
            

            from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
            
            oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
            
            @app.post("/token")
            async def login(form_data: OAuth2PasswordRequestForm = Depends()):
                # 验证用户名和密码
                user = authenticate_user(form_data.username, form_data.password)
                if not user:
                    raise HTTPException(status_code=401, detail="用户名或密码错误")
                
                access_token = create_access_token(data={"sub": user.username})
                return {"access_token": access_token, "token_type": "bearer"}
            

            SQLAlchemy集成

            from sqlalchemy import create_engine, Column, Integer, String
            from sqlalchemy.ext.declarative import declarative_base
            from sqlalchemy.orm import sessionmaker
            
            SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
            engine = create_engine(SQLALCHEMY_DATABASE_URL)
            SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
            Base = declarative_base()
            
            class User(Base):
                __tablename__ = "users"
                
                id = Column(Integer, primary_key=True, index=True)
                email = Column(String, unique=True, index=True)
                name = Column(String)
            
            Base.metadata.create_all(bind=engine)
            
            @app.post("/users/")
            def create_user(user: UserCreate, db: Session = Depends(get_db)):
                db_user = User(**user.dict())
                db.add(db_user)
                db.commit()
                db.refresh(db_user)
                return db_user
            

            from fastapi.middleware.cors import CORSMiddleware
            
            app.add_middleware(
                CORSMiddleware,
                allow_origins=["http://localhost:3000"],
                allow_credentials=True,
                allow_methods=["*"],
                allow_headers=["*"],
            )
            

            from fastapi import Request
            import time
            
            @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
            

            from fastapi import BackgroundTasks
            
            def write_log(message: str):
                with open("log.txt", mode="a") as log:
                    log.write(message + "n")
            
            @app.post("/send-notification/")
            async def send_notification(
                email: str,
                background_tasks: BackgroundTasks
            ):
                background_tasks.add_task(write_log, f"通知发送到: {email}")
                return {"message": "通知将在后台发送"}
            

            from fastapi import File, UploadFile
            
            @app.post("/uploadfile/")
            async def create_upload_file(file: UploadFile = File(...)):
                contents = await file.read()
                return {
                    "filename": file.filename,
                    "content_type": file.content_type,
                    "size": len(contents)
                }
            

            @app.post("/uploadfiles/")
            async def create_upload_files(files: list[UploadFile] = File(...)):
                return [{"filename": file.filename} for file in files]
            

            使用TestClient

            from fastapi.testclient import TestClient
            
            client = TestClient(app)
            
            def test_read_main():
                response = client.get("/")
                assert response.status_code == 200
                assert response.json() == {"message": "Hello World"}
            
            def test_create_item():
                response = client.post(
                    "/items/",
                    json={"name": "测试商品", "price": 99.99}
                )
                assert response.status_code == 201
                assert response.json()["name"] == "测试商品"
            

            import httpx
            
            @app.get("/external-api/")
            async def call_external_api():
                async with httpx.AsyncClient() as client:
                    response = await client.get("https://api.example.com/data")
                    return response.json()
            

            from sqlalchemy.orm import joinedload
            
            @app.get("/users/{user_id}/posts/")
            def get_user_posts(user_id: int, db: Session = Depends(get_db)):
                # 使用eager loading避免N+1查询问题
                user = db.query(User).options(
                    joinedload(User.posts)
                ).filter(User.id == user_id).first()
                return user.posts
            

            from functools import lru_cache
            
            @lru_cache(maxsize=128)
            def get_settings():
                return Settings()
            
            @app.get("/settings/")
            def read_settings(settings: Settings = Depends(get_settings)):
                return settings
            

            创建Dockerfile:

            FROM python:3.11-slim
            
            WORKDIR /app
            
            COPY requirements.txt .
            RUN pip install --no-cache-dir -r requirements.txt
            
            COPY . .
            
            CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
            

            # 使用Gunicorn + Uvicorn workers
            # 命令行运行:
            # gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
            

            from pydantic_settings import BaseSettings
            
            class Settings(BaseSettings):
                app_name: str = "FastAPI应用"
                database_url: str
                secret_key: str
                
                class Config:
                    env_file = ".env"
            
            settings = Settings()
            

            project/
            ├── app/
            │   ├── __init__.py
            │   ├── main.py
            │   ├── models/
            │   │   ├── __init__.py
            │   │   └── user.py
            │   ├── schemas/
            │   │   ├── __init__.py
            │   │   └── user.py
            │   ├── routers/
            │   │   ├── __init__.py
            │   │   └── users.py
            │   ├── dependencies.py
            │   └── database.py
            ├── tests/
            ├── requirements.txt
            └── .env

            from fastapi import APIRouter
            
            router = APIRouter(
                prefix="/users",
                tags=["users"],
                responses={404: {"description": "Not found"}}
            )
            
            @router.get("/")
            async def read_users():
                return [{"username": "user1"}]
            
            @router.get("/{user_id}")
            async def read_user(user_id: int):
                return {"user_id": user_id}
            
            # 在main.py中
            app.include_router(router)
            

            from fastapi import APIRouter
            
            api_v1 = APIRouter(prefix="/api/v1")
            api_v2 = APIRouter(prefix="/api/v2")
            
            @api_v1.get("/items/")
            async def get_items_v1():
                return {"version": "1.0"}
            
            @api_v2.get("/items/")
            async def get_items_v2():
                return {"version": "2.0", "data": []}
            
            app.include_router(api_v1)
            app.include_router(api_v2)
            

            FastAPI是一个强大而现代的Python Web框架,它结合了高性能、开发效率和优秀的开发者体验。通过本指南,你已经学习了:

            • FastAPI的核心概念和基础用法
            • 数据验证和序列化
            • 依赖注入系统
            • 认证和授权
            • 数据库集成
            • 性能优化技巧
            • 生产环境部署

            继续深入学习FastAPI的官方文档,并在实际项目中应用这些知识,你将能够构建出高性能、可维护的RESTful API应用。

            以上就是使用FastAPI构建高性能RESTful API的完整指南的详细内容,更多关于FastAPI构建高性能API的资料请关注风君子博客其它相关文章!

            您可能感兴趣的文章:

            • python基于FastAPI实现一个简易的在线用户统计功能
            • Python如何使用FastAPI玩转文件上传功能
            • Python FastAPI入门安装使用
            • python如何通过FastAPI构建复杂的Web API
            • Python 框架 FastAPI详解
            • Python 搭建 FastAPI 项目的详细过程

            站内搜索