当前位置: 首页 > news >正文

FastAPI 学习教程 · 第8部分

部署、测试与项目结构优化

💡 本部分目标:学会组织大型项目结构;编写自动化测试;使用 Docker 容器化应用;将 FastAPI 应用部署到免费云平台(如 Render)。


一、为什么需要良好的项目结构?

随着功能增加,把所有代码写在main.py中会变得难以维护。
合理的结构能提升:

  • 可读性:快速找到模型、路由、依赖
  • 可测试性:模块化便于单元测试
  • 协作效率:团队开发更顺畅

二、推荐项目结构(适用于中小型项目)

blog-api/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI 实例 & 中间件 │ ├── models.py # 数据库模型 │ ├── schemas.py # Pydantic 模型(请求/响应) │ ├── database.py # 数据库连接 & 会话 │ ├── security.py # 认证逻辑 │ ├── exceptions.py # 自定义异常 │ └── api/ │ ├── __init__.py │ ├── v1/ │ │ ├── __init__.py │ │ ├── posts.py # 文章相关路由 │ │ └── users.py # 用户相关路由 ├── tests/ │ ├── __init__.py │ ├── test_posts.py │ └── test_users.py ├── requirements.txt ├── Dockerfile └── README.md

🔑 核心思想:按功能分层 + 按资源分模块


三、重构现有代码(示例)

3.1app/database.py

# app/database.pyfromsqlmodelimportcreate_engine,Sessionfromsqlalchemy.poolimportStaticPool# 开发用 SQLite(内存数据库,测试更快)DATABASE_URL="sqlite://"engine=create_engine(DATABASE_URL,connect_args={"check_same_thread":False},poolclass=StaticPool,# 避免多线程问题)defget_session():withSession(engine)assession:yieldsessiondefcreate_db_and_tables():fromapp.modelsimportSQLModel SQLModel.metadata.create_all(engine)

3.2app/main.py

# app/main.pyfromfastapiimportFastAPIfromapp.databaseimportcreate_db_and_tablesfromapp.api.v1.postsimportrouterasposts_routerfromapp.api.v1.usersimportrouterasusers_router app=FastAPI(title="博客 API")# 初始化数据库@app.on_event("startup")defon_startup():create_db_and_tables()# 注册路由app.include_router(posts_router,prefix="/api/v1")app.include_router(users_router,prefix="/api/v1")

3.3app/api/v1/posts.py

# app/api/v1/posts.pyfromfastapiimportAPIRouter,Depends,HTTPExceptionfromsqlmodelimportSession,selectfromapp.databaseimportget_sessionfromapp.modelsimportPostfromapp.schemasimportPostCreate,PostRead router=APIRouter(tags=["文章"])@router.post("/posts/",response_model=PostRead,status_code=201)defcreate_post(post:PostCreate,session:Session=Depends(get_session)):db_post=Post.from_orm(post)session.add(db_post)session.commit()session.refresh(db_post)returndb_post

💡 使用APIRouter分离路由逻辑,通过include_router注册到主应用。


四、编写自动化测试(pytest)

测试能确保代码修改不会破坏现有功能。

4.1 安装 pytest

pipinstallpytest httpx
  • httpx:用于模拟 HTTP 请求(替代 requests)

4.2 编写测试用例

tests/test_posts.py
# tests/test_posts.pyimportpytestfromhttpximportAsyncClientfromapp.mainimportappfromapp.databaseimportcreate_db_and_tables# 创建测试客户端@pytest.fixturedefclient():create_db_and_tables()# 每次测试前重建数据库withAsyncClient(app=app,base_url="http://test")asac:yieldac@pytest.mark.asyncioasyncdeftest_create_post(client):response=awaitclient.post("/api/v1/posts/",json={"title":"测试文章","content":"内容","author":"alice"})assertresponse.status_code==201data=response.json()assertdata["title"]=="测试文章"assert"id"indata

4.3 运行测试

pytest tests/-v

绿色 PASS 表示测试通过!


五、Docker 容器化

Docker 让应用“一次构建,到处运行”。

5.1 创建Dockerfile

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

5.2 创建requirements.txt

fastapi uvicorn[standard] sqlmodel python-jose[cryptography] passlib[bcrypt] pytest httpx

5.3 构建并运行

# 构建镜像dockerbuild-tblog-api.# 运行容器dockerrun-p8000:8000 blog-api

访问 http://localhost:8000/docs 即可看到你的 API!


六、部署到 Render(免费云平台)

Render 提供免费 Web 服务托管(支持 Docker 和 Git 部署)。

步骤:

  1. 将代码推送到 GitHub 仓库
  2. 登录 Render → New Web Service
  3. 连接你的 GitHub 仓库
  4. 设置:
    • Build Command:pip install -r requirements.txt
    • Start Command:uvicorn app.main:app --host 0.0.0.0 --port $PORT
  5. 点击 “Create Web Service”

🌐 几分钟后,你会获得一个公开 URL(如https://blog-api.onrender.com

⚠️ 注意:免费版会休眠,首次访问稍慢。


七、环境变量管理(进阶)

敏感信息(如 JWT 密钥)不应写死在代码中。

使用python-dotenv

pipinstallpython-dotenv

创建.env文件:

SECRET_KEY=my-super-secret-key-change-in-prod DATABASE_URL=sqlite:///./prod.db

在代码中加载:

# app/config.pyfromdotenvimportload_dotenvimportos load_dotenv()SECRET_KEY=os.getenv("SECRET_KEY")DATABASE_URL=os.getenv("DATABASE_URL")

🔒.env文件应加入.gitignore,避免提交到 Git!


八、练习任务(动手实践)

🧠 请先自己尝试完成,再查看下方答案!

任务1:完善项目结构

  • 将现有代码按推荐结构拆分到app/目录
  • 确保uvicorn app.main:app --reload能正常启动

任务2:编写用户注册测试

  • tests/test_users.py
  • 测试 POST/api/v1/users/(假设你有注册接口)
  • 验证返回状态码和字段

任务3:创建 Docker 镜像并本地运行

  • 编写Dockerfilerequirements.txt
  • 构建并运行容器
  • 访问/docs确认服务正常

九、练习任务参考答案

任务1 答案

确保目录结构正确,关键文件内容如前文所示。
启动命令:

uvicorn app.main:app--reload

任务2 答案(假设用户模型存在)

# tests/test_users.py@pytest.mark.asyncioasyncdeftest_register_user(client):response=awaitclient.post("/api/v1/users/",json={"username":"charlie","email":"charlie@example.com","password":"pass123"})assertresponse.status_code==201data=response.json()assertdata["username"]=="charlie"assert"email"indata

任务3 答案

  1. requirements.txt包含所有依赖
  2. Dockerfile如前文所示
  3. 构建运行:
    dockerbuild-tmy-blog.dockerrun-p8000:8000 my-blog
  4. 浏览器访问 http://localhost:8000/docs

十、小结

在本部分,你学会了:

  • 组织专业级项目结构
  • 编写自动化测试(pytest + httpx)
  • 使用 Docker 容器化应用
  • 部署到免费云平台(Render)
  • 管理环境变量,提升安全性

🎉恭喜!你已经掌握了 FastAPI 从入门到部署的完整技能链!

http://www.jsqmd.com/news/421868/

相关文章:

  • AI模型——Ming-Lite-Omni-1.5多模态全能助手[特殊字符]
  • FastAPI 学习教程 · 第7部分
  • AI vs Human图像分类模型 [特殊字符][特殊字符]‍[特殊字符] 60K数据训练
  • 题解:洛谷 B2028 反向输出一个三位数
  • OpenClaw 架构设计全解析
  • 向量数据库基础认识
  • Anthropic CEO Dario Amodei:海啸已在地平线上,但没人在看
  • 加密狗防丢失与备份策略
  • 题解:洛谷 B2026 计算浮点数相除的余
  • fs模块-路径动态拼接的问题
  • Spark与Arctic集成:流批一体数据湖方案
  • AI辅助写作:提升技术文档创作效率的秘诀
  • 题解:洛谷 B2024 输出浮点数
  • 2026年AI智能产品开发行业谁在定义新标准?
  • 2.28总结
  • 2、Python数据结构与函数(配套函数)
  • 软考2026上半年报名在即,这几项资料请提前准备!
  • 基于STM32F103为主控的5KW 混合储能系统48V电池+500V光伏+220V逆变(AD...
  • 大数据处理中 Kafka 的安全配置与防护
  • 3、Python进阶操作
  • 题解:洛谷 B2022 输出保留 12 位小数的浮点数
  • Tita AI 场景化攻略:AI生成项目,让项目规划不再茫然
  • 博客索引
  • 3、Python进阶操作(配套答案)
  • AI提示设计市场需求大解密,提示工程架构师的机会窗口
  • 题解:洛谷 B2023 空格分隔输出
  • 2、Python数据结构与函数
  • SmolRTSP:在嵌入式系统中实现高效 RTSP 流媒体服务的开源实践
  • Qt实现自定义字符串生成二维码(附完整源码+详细解析)
  • 深圳猎头公司前十强权威榜单(2026最新版)——含深度分析及联系电话 - 品牌企业推荐师(官方)