返回专题首页

Python 专题

基于 FastAPI + SQLAlchemy 的 Blog API:项目开发与接口设计

有了前置认知之后,接下来就轮到真正的接口设计与开发实现。一个 API 项目真正考验的,往往不是“会不会写路由”,而是职责如何拆分、字段如何约定、错误如何表达,以及不同接口之间能否保持一致。

Python 专题第 34 篇 / 39 篇5 分钟

有了前置认知之后,接下来就轮到真正的接口设计与开发实现。一个 API 项目真正考验的,往往不是“会不会写路由”,而是职责如何拆分、字段如何约定、错误如何表达,以及不同接口之间能否保持一致。

这一节我们会以 Blog API 为主线,把路由层、服务层、数据层和接口契约放到一起考虑,看看一个更像样的后端项目,应该如何把结构和行为都组织得更清晰。

从路由到服务层的职责拆分

最容易写乱的 API 项目,往往是把参数解析、权限判断、事务处理、数据库操作、响应拼装全塞在路由函数里。

更合理的拆分通常是:

  • 路由层负责接收请求和返回响应;
  • 服务层负责业务规则;
  • 数据访问层负责持久化细节。

这不是为了层数好看,而是为了后面能更容易测试、复用和替换实现。

一个足够清楚的最小拆分,可以先长这样:

app/
  routers/articles.py
  services/article_service.py
  repositories/article_repository.py
  schemas/article.py
  models/article.py

它不一定是唯一答案,但至少能帮你把“入口、业务、持久化、模型定义”这几层分清楚。

文章、分类与标签接口设计

Blog API 很适合练接口设计,因为它天然会涉及:

  • 文章 CRUD;
  • 分类筛选;
  • 标签关联;
  • 列表查询与详情读取。

这里真正值得练习的,不只是路径怎么命名,而是资源边界是否清楚。比如分类和标签到底是独立资源,还是文章附属字段;创建文章时是否支持一起绑定标签;更新接口是全量还是部分更新。

这些问题都不是语法问题,而是接口契约问题。

如果用 Blog API 来演练,一个比较实用的接口清单可以先从这里开始:

| 方法 | 路径 | 作用 || --- | --- | --- || GET | /articles | 分页获取文章列表 || GET | /articles/{id} | 获取文章详情 || POST | /articles | 创建文章 || PATCH | /articles/{id} | 更新文章 || DELETE | /articles/{id} | 删除文章 |

这张表的意义,不是追求完整,而是先把资源边界和基础动词定清楚。

请求参数、响应结构与状态码约定

一个 API 项目一旦接口多起来,最怕的就是风格散。

例如:

  • 有的列表返回 items,有的返回 data
  • 有的错误字段叫 message,有的叫 detail
  • 有的创建接口返回 200,有的返回 201;

这种不一致会迅速放大前后端沟通成本。

所以状态码、字段命名、分页结构、错误响应格式,都应该尽早形成统一约定。

例如,创建文章接口的请求和响应可以先约定成这样:

请求体:

{
  "title": "FastAPI 入门",
  "content": "这是一篇示例文章",
  "tags": ["python", "web"]
}

成功响应:

{
  "id": 1,
  "title": "FastAPI 入门",
  "content": "这是一篇示例文章",
  "tags": ["python", "web"],
  "created_at": "2026-04-10T13:00:00Z"
}

错误响应:

{
  "detail": "article not found"
}

数据校验、异常处理与事务边界

项目开发过程中,很容易把“数据能进来”误当成“接口设计完成了”。其实真正稳定的 API 还要明确:

  • 哪一层做输入校验;
  • 哪一层做业务规则校验;
  • 哪一层控制事务提交与回滚;
  • 异常如何转换成对外响应。

如果这些边界模糊,后面一定会出现某些错误在路由层处理、某些在服务层处理、某些直接穿透到最外层的混乱局面。

分页、筛选与查询优化基础

只要有列表接口,分页几乎就是必选项。

分页的重点不只是 limitoffset,还包括:

  • 默认排序规则;
  • 筛选参数命名;
  • 响应里是否返回总数;
  • 大页码场景下的性能边界。

这类细节看似普通,但它们恰恰最能体现一个 API 是否真的经过了认真设计。

一个最小分页返回结构,也很值得尽早统一:

{
  "items": [
    {
      "id": 1,
      "title": "FastAPI 入门"
    }
  ],
  "total": 24,
  "page": 1,
  "page_size": 10
}

只要这个结构在列表接口里稳定下来,前端联调和后续维护都会轻松很多。

如何保持接口设计的一致性?

一致性通常不是靠“每次都临时想一下”,而是靠提前定义风格并在项目中持续复用。

例如:

  • 统一响应模型;
  • 统一错误模型;
  • 统一分页结构;
  • 统一路由命名风格;
  • 统一依赖注入与服务调用方式。

这些统一动作,会显著降低项目规模扩大后的维护成本。

总结与预告

这一节我们围绕 Blog API 把接口设计和职责拆分真正落到了代码结构的思路上。一个接口项目是否易于维护,往往就取决于这些看似细小的约定是否在一开始就被认真对待。

下一节我们会把这个实战项目推进到收尾阶段,从测试、部署到上线检查,补齐它成为一个完整案例所需要的最后一环。