零基础入门python46:FastAPI 配置、环境变量与依赖注入
零基础入门python46FastAPI 配置、环境变量与依赖注入一、上一篇课后练习讲解上一篇练习围绕“ASGI、应用对象与自动文档”。参考做法是先运行上一篇的测试再用一个成功请求和一个失败请求验证边界本篇在同一项目上增加新能力。上一篇课后练习完整答案上一篇练习已经落实到完整文件运行下面代码可以观察本篇要求的成功和失败状态数据库写入全部放在明确事务边界内。答案要点FastAPI main 创建应用、注册路由并提供 /healthASGI 参数错误在业务函数前返回 422/docs 可访问。完整答案文件app/main.py完整参考答案文件完整文件app/main.pyfromfastapiimportFastAPI appFastAPI(titleBlog Community API)app.get(/health)defhealth():return{status:ok}验收运行项目测试FastAPI/Flask 使用 python -m pytest -qDjango 使用 python manage.py test再按本文 curl 或 Docker 命令检查预期状态码。完整参考答案文件下面是交付项目中真实存在的完整文件 fastapi-blog/app/main.py。它覆盖本篇新增逻辑以及前文已经完成的依赖代码复制单个函数会丢失上下文因此这里提供整份文件。fromfastapiimportFastAPI,Requestfromfastapi.responsesimportJSONResponsefrom.importai,articles,auth,extrasfrom.databaseimportBase,engine Base.metadata.create_all(engine)appFastAPI(titleBlog Community API,version2.0)app.include_router(auth.router);app.include_router(articles.router);app.include_router(ai.router);app.include_router(extras.router)app.get(/api/health)defhealth():return{status:ok}app.exception_handler(ValueError)defvalue_error_handler(request:Request,exc:ValueError):returnJSONResponse(status_code400,content{code:BAD_REQUEST,message:str(exc)})requirements.txtfastapi0.115.6 uvicorn[standard]0.34.0安装并启动python-m venv.venv.venv\Scripts\python.exe-m pip install-r requirements.txt.venv\Scripts\python.exe-m uvicorn app.main:app--reloadapp.main:app的含义是“导入 app/main.py 中名为 app 的对象”。--reload只用于开发生产环境使用固定 worker 和进程管理器。二、本篇要解决的真实问题把数据库 URL、JWT 密钥和调试开关放进配置层Depends 让路由声明需要什么而不是自己创建全局 Session。三、请求是怎样走完整条链路的客户端请求 → 路由匹配 → Pydantic 校验 → Depends 注入用户/Session → SQLAlchemy 查询或业务服务 → 提交事务 → 响应模型序列化。每一步都有明确责任排错时按这个顺序定位。四、先看一个最小代码片段router.get(/api/health)defhealth():return{status:ok}这里的注释不是装饰它说明数据从哪里来、为什么不能相信客户端以及失败时系统应保持什么状态。五、完整文件代码app/database.py当前阶段完整文件fromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportDeclarativeBase,sessionmaker DATABASE_URLsqlite:///./blog.dbenginecreate_engine(DATABASE_URL,connect_args{check_same_thread:False})SessionLocalsessionmaker(bindengine,autoflushFalse,expire_on_commitFalse)classBase(DeclarativeBase):passdefget_db():dbSessionLocal()try:yielddbfinally:db.close()阅读方法先找路由函数再找它的 Depends、输入 schema、数据库操作和 response_model这五处合起来才是一个功能。app/main.py当前阶段完整文件fromfastapiimportFastAPI,Requestfromfastapi.responsesimportJSONResponsefrom.importai,articles,auth,extrasfrom.databaseimportBase,engine Base.metadata.create_all(engine)appFastAPI(titleBlog Community API,version2.0)app.include_router(auth.router);app.include_router(articles.router);app.include_router(ai.router);app.include_router(extras.router)app.get(/api/health)defhealth():return{status:ok}app.exception_handler(ValueError)defvalue_error_handler(request:Request,exc:ValueError):returnJSONResponse(status_code400,content{code:BAD_REQUEST,message:str(exc)})阅读方法先找路由函数再找它的 Depends、输入 schema、数据库操作和 response_model这五处合起来才是一个功能。六、安装、启动与验收..\..\.venv\Scripts\python.exe-m pip install-r requirements.txt..\..\.venv\Scripts\python.exe-m pytest-q..\..\.venv\Scripts\python.exe-m uvicorn app.main:app--reload打开/docs按顺序完成注册、登录、创建文章、分页查询、修改删除、评论点赞。错误请求必须看到明确状态码校验错误 422未登录 401无权限 403重复点赞 409。测试应全部通过。七、本篇验收清单能指出输入校验发生在哪个 schema。能解释 Session 何时提交、何时回滚。能用第二个用户验证资源隔离。能复现一个失败场景并说明原因。八、课后练习围绕“配置、环境变量与依赖注入”新增一个测试用例写出请求、预期响应和断言下一篇开头会给出参考实现并继续使用本项目。五、配置对象和依赖注入让代码适应三种环境数据库地址、JWT 密钥和调试开关属于配置不应该散落在路由函数里。配置对象在启动时校验依赖注入则让测试可以替换它fromfunctoolsimportlru_cachefrompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):app_name:strblog-apidatabase_url:strsqlite:///./blog.dbjwt_secret:strdebug:boolFalsemodel_configSettingsConfigDict(env_file.env,extraignore)lru_cachedefget_settings()-Settings:# 只缓存配置对象不缓存数据库连接测试可清空缓存换环境。returnSettings()本地 .env 示例JWT_SECRETdev-secret-for-local-only DATABASE_URLsqlite:///./blog.db DEBUGtrue缺少 JWT_SECRET 时应该启动失败而不是偷偷使用公开的默认密钥。测试可以用 app.dependency_overrides[get_settings] 替换配置结束时在 finally 中清理覆盖。这样开发、测试、生产共用同一套路由差异只由环境提供。验收时先用不含密钥的环境启动记录清晰的校验错误再恢复变量访问 health。PowerShell 中用 Get-ChildItem Env:JWT_SECRET 检查当前进程是否真的看到变量。常见事故是 .env 被提交到 Git或在一个终端设置变量、另一个终端启动服务。六、当前项目中的完整文件对照阅读七、配置变更如何被验证为 Settings 写三条测试没有 JWT_SECRET 时构造对象抛 ValidationError设置合法值后能读取 database_url环境变量覆盖默认值。测试结束清理 os.environ避免用例顺序影响结果。配置项还应分级可以公开的服务名、需要保护的密钥、可以热更新的限流阈值。密钥不应该打印到启动日志即便 debugTrue 也不能把完整 Settings 对象 repr 出来。部署时将 .env.example 提交到仓库里面只放字段名和示例占位值。八、补充代码文件本篇结束完整模块文件本节不是代码片段而是本篇结束时该模块的完整版本。请先备份旧文件再整体替换替换后重新运行本篇命令和测试。阅读时重点看本篇新增的函数、事务边界和错误处理未涉及的代码先不要自行删减。app/database.pyfromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportDeclarativeBase,sessionmaker DATABASE_URLsqlite:///./blog.dbenginecreate_engine(DATABASE_URL,connect_args{check_same_thread:False})SessionLocalsessionmaker(bindengine,autoflushFalse,expire_on_commitFalse)classBase(DeclarativeBase):passdefget_db():dbSessionLocal()try:yielddbfinally:db.close()
