尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

FastAPI实战:从设计哲学到生产部署的完整指南

FastAPI实战:从设计哲学到生产部署的完整指南 最近两年我观察到很多从其他语言转过来的开发者或者刚接触后端开发的朋友在面对 Python 的 Web 框架选择时常常会陷入一种“选择困难”。他们知道 Flask 轻量但生态复杂Django 大而全但学习曲线陡峭而 FastAPI 这个名字虽然高频出现但很多人对它的理解还停留在“一个很快的 API 框架”或者“用了 Pydantic 和类型提示”的层面。这种理解没错但太浅了浅到不足以支撑你做出“是否用它来启动一个新项目”的决定更不足以让你在实战中游刃有余。FastAPI 真正的价值远不止于“快”。它的核心是用一套极其优雅的开发者体验DX把现代 Python 的类型系统、异步生态和 API 文档自动化无缝地编织在了一起。它解决的痛点不是“我的接口响应慢了 50 毫秒”而是“我如何用更少的代码、更清晰的逻辑、更自动化的工具来构建和维护一个健壮、可扩展且易于协作的 API 服务”。当你理解了这一点再看那些参数校验、依赖注入、自动文档就不再是孤立的功能点而是一个完整工作流中的关键齿轮。所以这篇文章不会是一个简单的功能罗列或“Hello World”教程。我想带你走的是一条从“知道”到“会用”再到“敢用于生产”的路径。我们会从最核心的设计哲学切入理解它为什么这样设计然后搭建一个麻雀虽小五脏俱全的实战项目把各个部件串联起来接着深入那些决定项目能否长期稳定运行的关键配置和“坑点”最后探讨如何将它融入一个现代的、工程化的开发流程。我们的目标不是复制官网示例而是让你获得一种“FastAPI 思维”能够自信地用它来解决真实世界的问题。1. 重新理解 FastAPI它到底改变了什么在动手写第一行代码之前我们需要先达成一个共识FastAPI 不是一个“更快版本的 Flask”。如果你带着 Flask 的思维定式去用它可能会觉得束手束脚或者浪费了它最强大的能力。它的改变是根本性的主要体现在三个层面。1.1 第一层改变从“运行时校验”到“开发时定义”在传统的 Web 框架里参数校验通常发生在请求到达视图函数之后。你需要手动从request对象里提取数据然后用if-else或者第三方库如wtforms、marshmallow来检查数据是否合法。这个过程容易出错代码冗长而且校验逻辑和业务逻辑常常纠缠在一起。FastAPI 通过深度集成 Pydantic把这个过程彻底前置了。你在函数签名里用 Python 类型提示Type Hints和 Pydantic 模型定义参数的那一刻校验规则就已经确定了。框架会在请求进入你的业务函数之前自动完成数据解析、类型转换和校验。如果校验失败客户端会直接收到一个结构化的 422 错误响应根本不会执行到你的业务代码。这意味着什么意味着你的函数可以“信任”它的输入。你不再需要写一堆防御性代码来检查id是不是整数、email格式对不对、page是否大于 0。这些工作被框架接管了你的函数体可以专注于真正的业务逻辑。这种模式极大地提升了代码的简洁性和可读性也减少了潜在的 Bug。1.2 第二层改变依赖注入DI作为一等公民依赖注入不是什么新概念但在 FastAPI 里它被设计得如此自然和强大以至于成了组织代码的核心模式。你可以把任何可复用的逻辑——数据库会话、认证令牌验证、权限检查、配置读取——声明为“依赖项”。这些依赖项本身也是普通的 Python 函数或可调用对象FastAPI 会自动解析它们的参数并在需要时执行它们将结果“注入”到你的路径操作函数中。这带来了几个巨大的好处代码复用与解耦认证逻辑写一次在所有需要认证的接口中声明即可。可测试性在单元测试中你可以轻松地用模拟对象Mock替换真实的依赖。清晰的依赖关系看一眼函数签名就知道这个接口依赖哪些外部资源数据库、缓存、第三方服务等。很多新手会忽略依赖注入或者觉得它“太复杂”。但恰恰相反善用依赖注入是写出可维护的 FastAPI 代码的关键。它让你的代码从“面条式”的流程变成了由清晰模块组装而成的乐高积木。1.3 第三层改变开箱即用的“API 契约即文档”对于任何需要前后端协作或对外提供服务的 API 项目文档都是噩梦。代码改了文档忘了更新最后形同虚设。FastAPI 基于 OpenAPI 和 JSON Schema 标准自动从你的代码类型提示、Pydantic 模型、路径参数生成交互式 API 文档Swagger UI 和 ReDoc。这不仅仅是“自动生成”那么简单。它建立了一种“代码即契约”的强一致性。你的接口长什么样文档就长什么样两者永远同步。前端开发者可以直接在 Swagger UI 里尝试调用接口看到真实的请求和响应结构这极大地减少了沟通成本。更重要的是它鼓励甚至是强迫开发者用清晰、标准的类型来定义接口这本身就是一种最佳实践。把这三点结合起来看FastAPI 提供的是一个高度集成、开发者友好、符合现代工程实践的全套解决方案。它用 Python 语言最新的特性类型提示、异步重新定义了编写 Web API 的体验。理解了这些我们才能更好地利用它而不是仅仅把它当作一个路由工具。2. 从零搭建一个“五脏俱全”的实战项目现在让我们暂时忘掉那些抽象的概念动手搭建一个真实的项目。这个项目不会太复杂但会涵盖 FastAPI 最核心的部件路由、Pydantic 模型、依赖注入、数据库操作ORM、中间件和静态文件。我们假设要构建一个简单的“任务管理”API。2.1 项目结构与环境搭建首先建立一个清晰的项目结构。混乱的目录是项目腐化的开始。fastapi_todo_project/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI 应用实例和核心配置 │ ├── core/ # 核心配置、依赖、工具 │ │ ├── __init__.py │ │ ├── config.py # 配置文件从环境变量读取 │ │ ├── database.py # 数据库连接会话SQLAlchemy │ │ └── dependencies.py # 全局依赖项如获取当前用户 │ ├── models/ # SQLAlchemy 数据模型对应数据库表 │ │ ├── __init__.py │ │ └── task.py │ ├── schemas/ # Pydantic 模型对应请求/响应体 │ │ ├── __init__.py │ │ └── task.py │ ├── crud/ # 数据库增删改查操作 │ │ ├── __init__.py │ │ └── task.py │ ├── api/ # 路由端点 │ │ ├── __init__.py │ │ └── v1/ # API 版本目录 │ │ ├── __init__.py │ │ ├── endpoints/ │ │ │ ├── __init__.py │ │ │ └── tasks.py # 任务相关的路由 │ │ └── api.py # v1 版本的路由聚合 │ └── static/ # 静态文件可选 └── requirements.txt在requirements.txt中我们至少需要fastapi0.104.1 uvicorn[standard]0.24.0 sqlalchemy2.0.23 pydantic2.5.0 pydantic-settings2.1.0 python-dotenv1.0.0 # 数据库驱动例如 PostgreSQL psycopg2-binary2.9.9 # 或 SQLite # sqlite3 (标准库)使用虚拟环境安装pip install -r requirements.txt。2.2 核心配置与数据库连接在app/core/config.py中我们使用pydantic-settings来管理配置这是比直接读os.environ更优雅和安全的方式。from pydantic_settings import BaseSettings from pydantic import PostgresDsn, validator from typing import Optional class Settings(BaseSettings): PROJECT_NAME: str FastAPI Todo API API_V1_STR: str /api/v1 # 数据库配置 POSTGRES_SERVER: str localhost POSTGRES_USER: str postgres POSTGRES_PASSWORD: str POSTGRES_DB: str todo_db SQLALCHEMY_DATABASE_URI: Optional[PostgresDsn] None validator(SQLALCHEMY_DATABASE_URI, preTrue) def assemble_db_connection(cls, v: Optional[str], values: dict) - str: if isinstance(v, str): return v # 如果未提供 URI则根据其他字段拼接 return PostgresDsn.build( schemepostgresql, usernamevalues.get(POSTGRES_USER), passwordvalues.get(POSTGRES_PASSWORD), hostvalues.get(POSTGRES_SERVER), pathf{values.get(POSTGRES_DB) or }, ) class Config: env_file .env # 从 .env 文件加载配置 case_sensitive True settings Settings()在项目根目录创建.env文件不要提交到版本控制POSTGRES_USERyour_user POSTGRES_PASSWORDyour_password POSTGRES_SERVERlocalhost POSTGRES_DBtodo_db接着在app/core/database.py中设置 SQLAlchemyfrom sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from app.core.config import settings # 创建数据库引擎 engine create_engine( settings.SQLALCHEMY_DATABASE_URI.unicode_string(), pool_pre_pingTrue, # 在从连接池取连接前先 ping 一下避免连接失效 echoTrue # 开发时打开可以看到生成的 SQL ) # 创建本地会话工厂 SessionLocal sessionmaker(autocommitFalse, autoflushFalse, bindengine) # 声明基类所有数据模型都继承它 Base declarative_base() # 依赖项获取数据库会话 def get_db(): 依赖项函数为每个请求提供一个独立的数据库会话。 请求处理完毕后自动关闭会话。 db SessionLocal() try: yield db finally: db.close()2.3 定义数据模型与 Pydantic 模式这是体现 FastAPI 设计哲学的关键一步。我们区分SQLAlchemy 模型对应数据库表和Pydantic 模式对应 API 的请求/响应体。app/models/task.py:from sqlalchemy import Column, Integer, String, Boolean, DateTime, func from app.core.database import Base class Task(Base): __tablename__ tasks id Column(Integer, primary_keyTrue, indexTrue) title Column(String(255), nullableFalse) description Column(String(1024)) is_completed Column(Boolean, defaultFalse) created_at Column(DateTime(timezoneTrue), server_defaultfunc.now()) updated_at Column(DateTime(timezoneTrue), onupdatefunc.now())app/schemas/task.py:from pydantic import BaseModel, ConfigDict from datetime import datetime from typing import Optional # 创建任务时使用的模式不需要 id 和 timestamps class TaskCreate(BaseModel): title: str description: Optional[str] None is_completed: bool False # 更新任务时使用的模式所有字段可选 class TaskUpdate(BaseModel): title: Optional[str] None description: Optional[str] None is_completed: Optional[bool] None # 从数据库读取任务后返回的模式 class TaskInDB(BaseModel): id: int title: str description: Optional[str] is_completed: bool created_at: datetime updated_at: Optional[datetime] # Pydantic V2 配置允许从 ORM 对象如 SQLAlchemy创建实例 model_config ConfigDict(from_attributesTrue)注意TaskInDB中的model_config ConfigDict(from_attributesTrue)。这行配置至关重要它允许我们直接将 SQLAlchemy 模型实例传入TaskInDB进行验证和序列化而无需先手动转换成字典。这是实现简洁 CRUD 的关键。2.4 编写 CRUD 层与 API 端点CRUD 层app/crud/task.py封装所有数据库操作from sqlalchemy.orm import Session from app.models.task import Task from app.schemas.task import TaskCreate, TaskUpdate from typing import List, Optional def get_task(db: Session, task_id: int) - Optional[Task]: return db.query(Task).filter(Task.id task_id).first() def get_tasks(db: Session, skip: int 0, limit: int 100) - List[Task]: return db.query(Task).offset(skip).limit(limit).all() def create_task(db: Session, task_in: TaskCreate) - Task: # **task_in.dict() 将 Pydantic 对象转为字典 db_task Task(**task_in.model_dump()) db.add(db_task) db.commit() db.refresh(db_task) # 从数据库重新加载获取生成的 id 等默认值 return db_task def update_task(db: Session, db_task: Task, task_in: TaskUpdate) - Task: # 获取更新数据排除未设置的字段 update_data task_in.model_dump(exclude_unsetTrue) for field, value in update_data.items(): setattr(db_task, field, value) db.add(db_task) db.commit() db.refresh(db_task) return db_task def delete_task(db: Session, task_id: int) - Optional[Task]: db_task get_task(db, task_id) if db_task: db.delete(db_task) db.commit() return db_task现在在app/api/v1/endpoints/tasks.py中编写真正的 API 端点from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from app.core.database import get_db from app import crud, schemas router APIRouter() router.post(/, response_modelschemas.TaskInDB, status_codestatus.HTTP_201_CREATED) def create_task( task_in: schemas.TaskCreate, db: Session Depends(get_db) ): 创建新任务。 return crud.create_task(dbdb, task_intask_in) router.get(/, response_modelList[schemas.TaskInDB]) def read_tasks( skip: int 0, limit: int 100, db: Session Depends(get_db) ): 获取任务列表支持分页。 tasks crud.get_tasks(db, skipskip, limitlimit) return tasks router.get(/{task_id}, response_modelschemas.TaskInDB) def read_task( task_id: int, db: Session Depends(get_db) ): 根据 ID 获取单个任务。 db_task crud.get_task(db, task_idtask_id) if db_task is None: raise HTTPException(status_code404, detailTask not found) return db_task router.put(/{task_id}, response_modelschemas.TaskInDB) def update_task( task_id: int, task_in: schemas.TaskUpdate, db: Session Depends(get_db) ): 更新任务。 db_task crud.get_task(db, task_idtask_id) if db_task is None: raise HTTPException(status_code404, detailTask not found) return crud.update_task(dbdb, db_taskdb_task, task_intask_in) router.delete(/{task_id}, response_modelschemas.TaskInDB) def delete_task( task_id: int, db: Session Depends(get_db) ): 删除任务。 db_task crud.delete_task(db, task_idtask_id) if db_task is None: raise HTTPException(status_code404, detailTask not found) return db_task注意每个路径操作函数都通过db: Session Depends(get_db)声明了对数据库会话的依赖。FastAPI 会自动为每个请求调用get_db提供会话并在请求结束后关闭它。response_model参数则确保了我们的响应数据会被自动序列成TaskInDB模式定义的格式。2.5 组装应用并运行在app/api/v1/api.py中聚合所有端点from fastapi import APIRouter from app.api.v1.endpoints import tasks api_router APIRouter() api_router.include_router(tasks.router, prefix/tasks, tags[tasks])在app/main.py中创建 FastAPI 应用实例并挂载路由from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.core.config import settings from app.api.v1.api import api_router from app.core.database import engine, Base # 创建数据库表生产环境应使用 Alembic 迁移 Base.metadata.create_all(bindengine) app FastAPI( titlesettings.PROJECT_NAME, openapi_urlf{settings.API_V1_STR}/openapi.json ) # 设置 CORS根据前端地址配置 app.add_middleware( CORSMiddleware, allow_origins[http://localhost:3000], # 前端地址 allow_credentialsTrue, allow_methods[*], allow_headers[*], ) # 挂载 API 路由 app.include_router(api_router, prefixsettings.API_V1_STR) app.get(/) def read_root(): return {message: Welcome to the Todo API}最后使用 Uvicorn 运行应用uvicorn app.main:app --reload --host 0.0.0.0 --port 8000访问http://localhost:8000/docs你将看到自动生成的、功能完整的 Swagger UI 文档。你可以直接在这里测试创建、查询、更新和删除任务。至此一个结构清晰、功能完整的 FastAPI 后端项目骨架就搭建完成了。3. 超越“跑通”生产级配置与关键“坑点”项目能运行只是第一步。要让它在生产环境中稳定、高效、易维护还需要关注以下几个关键方面。这些往往是新手教程里不会深入讲但实际项目中一定会遇到的问题。3.1 依赖管理与虚拟环境的最佳实践requirements.txt是基础但对于生产项目更推荐使用pyproject.toml配合poetry或pdm进行依赖管理。它们能更好地处理依赖锁版本和虚拟环境隔离。以poetry为例安装 Poetrypip install poetry或使用官方安装脚本。初始化项目在项目根目录运行poetry init根据提示填写信息。添加依赖poetry add fastapi uvicorn sqlalchemy pydantic psycopg2-binary安装依赖poetry install。这会创建一个虚拟环境并安装所有依赖。运行应用poetry run uvicorn app.main:app --reload使用poetry的好处是pyproject.toml和poetry.lock文件一起能确保在任何机器上复现完全一致的依赖环境避免“在我机器上是好的”这类问题。3.2 数据库迁移不要再用create_all在开发中我们用了Base.metadata.create_all(bindengine)来创建表。在生产环境中绝对不要这样做。一旦表结构需要修改增加字段、修改类型create_all会先删除表再重建导致数据丢失。正确的工具是Alembic。它是 SQLAlchemy 作者编写的数据库迁移工具。安装poetry add alembic或pip install alembic初始化在项目根目录运行alembic init alembic。配置修改alembic.ini中的sqlalchemy.url或更推荐在alembic/env.py中动态从我们的settings读取。创建迁移脚本修改了models/下的模型后运行alembic revision --autogenerate -m 描述Alembic 会对比模型与数据库的差异生成升级脚本。执行迁移alembic upgrade head。将数据库变更纳入版本控制是团队协作和持续部署的基石。3.3 异步数据库与请求生命周期我们的示例使用了同步的 SQLAlchemy。对于 I/O 密集型的 API使用异步驱动如asyncpg配合sqlalchemy[asyncio]能更好地发挥 FastAPI 的异步优势。但这会引入一些复杂性会话管理异步上下文管理器。依赖项需要使用async def并正确处理。ORM 操作需要使用await。关键建议如果你的应用主要是 CRUD 操作且数据库不是绝对性能瓶颈使用同步 SQLAlchemy 多进程/多线程的服务器如 Uvicorn with workers是完全可行的且更简单。不要为了“异步”而异步除非你明确遇到了同步数据库驱动导致的阻塞问题并且团队熟悉异步编程模式。另一个相关概念是后台任务。如果有一个耗时操作如发送邮件、处理图片你不应该让它阻塞当前请求的响应。FastAPI 提供了BackgroundTasksfrom fastapi import BackgroundTasks def write_log(message: str): with open(log.txt, modea) as log: log.write(message) router.post(/task/{task_id}) async def run_task( task_id: int, background_tasks: BackgroundTasks ): background_tasks.add_task(write_log, fProcessed task {task_id}) return {message: Task started in background}3.4 认证与授权依赖注入的完美用例认证是依赖注入最能大显身手的场景。假设我们使用 JWTJSON Web Token创建依赖项(app/core/dependencies.py)from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt from app.core.config import settings oauth2_scheme OAuth2PasswordBearer(tokenUrlf{settings.API_V1_STR}/auth/login) async def get_current_user(token: str Depends(oauth2_scheme)): credentials_exception HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detailCould not validate credentials, headers{WWW-Authenticate: Bearer}, ) try: payload jwt.decode(token, settings.SECRET_KEY, algorithms[settings.ALGORITHM]) username: str payload.get(sub) if username is None: raise credentials_exception except JWTError: raise credentials_exception # 这里应该去数据库查询用户这里简化为从 payload 获取 user {username: username} return user在需要认证的接口中使用router.get(/me/, response_modelschemas.User) async def read_users_me(current_user: dict Depends(get_current_user)): return current_user通过这种方式认证逻辑被完美地解耦和复用。你还可以创建更复杂的依赖项比如get_current_active_user依赖get_current_user并检查用户是否活跃实现权限的层级组合。3.5 异常处理与自定义错误响应FastAPI 有完善的异常处理机制。除了使用HTTPException你还可以自定义异常处理器以统一的格式返回错误。from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from pydantic import ValidationError app FastAPI() app.exception_handler(ValidationError) async def validation_exception_handler(request: Request, exc: ValidationError): # 处理 Pydantic 校验错误通常由请求体不符模式引起 return JSONResponse( status_code422, content{ detail: exc.errors(), body: exc.body }, ) class UnicornException(Exception): def __init__(self, name: str): self.name name app.exception_handler(UnicornException) async def unicorn_exception_handler(request: Request, exc: UnicornException): return JSONResponse( status_code418, content{message: fOops! {exc.name} did something. There goes a rainbow...}, )统一的错误响应格式对于前端调试和日志收集都非常有帮助。3.6 日志、监控与性能日志使用 Python 标准库的logging模块为你的应用配置结构化日志JSON 格式并集成到像 Logstash 或 Datadog 这样的日志系统中。监控使用prometheus-client暴露应用指标请求数、延迟、错误率并用 Grafana 展示。性能使用uvicorn的--workers参数利用多核 CPU。对于 CPU 密集型任务考虑使用BackgroundTasks或消息队列如 Celery将其移出请求循环。4. 从项目到工程部署、测试与持续集成一个可用的项目和一个可工程化维护的项目之间隔着测试、部署和自动化流程。4.1 编写测试保证重构的勇气没有测试的项目没人敢轻易修改。FastAPI 提供了TestClient让编写 API 测试变得简单。tests/test_tasks.py:from fastapi.testclient import TestClient from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from app.main import app from app.core.database import Base, get_db import pytest # 为测试创建独立的内存数据库 SQLALCHEMY_DATABASE_URL sqlite:///./test.db engine create_engine(SQLALCHEMY_DATABASE_URL, connect_args{check_same_thread: False}) TestingSessionLocal sessionmaker(autocommitFalse, autoflushFalse, bindengine) # 重写依赖项让测试使用测试数据库 def override_get_db(): try: db TestingSessionLocal() yield db finally: db.close() app.dependency_overrides[get_db] override_get_db client TestClient(app) def setup_module(module): 在每个测试文件开始时运行创建表 Base.metadata.create_all(bindengine) def teardown_module(module): 在每个测试文件结束时运行删除表 Base.metadata.drop_all(bindengine) def test_create_task(): response client.post( /api/v1/tasks/, json{title: Test Task, description: A test} ) assert response.status_code 201 data response.json() assert data[title] Test Task assert id in data def test_read_task_not_found(): response client.get(/api/v1/tasks/999) assert response.status_code 404使用pytest运行测试pytest tests/ -v。将测试集成到 CI/CD 流程中确保每次提交都不会破坏现有功能。4.2 容器化部署Docker 化你的应用创建DockerfileFROM python:3.11-slim WORKDIR /app # 安装系统依赖如需要编译 psycopg2 RUN apt-get update apt-get install -y \ gcc \ postgresql-client \ rm -rf /var/lib/apt/lists/* # 复制依赖文件并安装 COPY pyproject.toml poetry.lock ./ RUN pip install poetry poetry config virtualenvs.create false poetry install --no-root --no-interaction --no-ansi # 复制应用代码 COPY . . # 运行迁移生产环境可能需要在启动脚本中处理 # RUN alembic upgrade head CMD [uvicorn, app.main:app, --host, 0.0.0.0, --port, 80, --workers, 4]创建docker-compose.yml来编排应用和数据库version: 3.8 services: db: image: postgres:15 environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U ${POSTGRES_USER}] interval: 10s timeout: 5s retries: 5 web: build: . command: sh -c alembic upgrade head uvicorn app.main:app --host 0.0.0.0 --port 80 --workers 4 environment: POSTGRES_SERVER: db POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} depends_on: db: condition: service_healthy ports: - 8000:80 restart: unless-stopped volumes: postgres_data:使用docker-compose up -d即可一键启动完整的服务栈。4.3 持续集成/持续部署 (CI/CD)在.github/workflows/ci.yml中配置 GitHub Actionsname: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest services: postgres: image: postgres:15 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: test_db options: - --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkoutv3 - name: Set up Python uses: actions/setup-pythonv4 with: python-version: 3.11 - name: Install dependencies run: | pip install poetry poetry install - name: Run tests env: SQLALCHEMY_DATABASE_URI: postgresql://postgres:postgreslocalhost/test_db run: | poetry run pytest tests/ -v这个流程会在每次推送代码或发起拉取请求时自动运行测试确保代码质量。走到这一步你的 FastAPI 项目已经从一个简单的脚本进化成了一个结构清晰、易于测试、便于部署、可以协同开发的工程化应用。这其中的每一步——从理解设计哲学、搭建项目骨架、配置生产环境到建立自动化流程——都是在为项目的长期健康和维护性投资。FastAPI 提供的优秀开发体验只有结合这些工程实践才能发挥出最大的价值。它不仅仅是一个写 API 的工具更是推动你走向更规范、更高效开发流程的催化剂。
返回列表