FastAPI 零基础入门教程:写过 Node.js,就能轻松学会 Python 后端开发(一)

2 阅读14分钟

2026 版

Node.js 开发者转 Python

包含完整 CRUD 实战

这篇文章专门写给有 Node.js、Express、NestJS 开发经验,但刚开始学习 Python FastAPI 的开发者。

核心思路:不从 Python 基础语法开始讲,而是直接拿 Node.js 对比 FastAPI,让你用熟悉的开发思维快速上手。

学完这篇文章,你将能够:

  • 理解 FastAPI、Express、NestJS 的关系。
  • 使用 Python 创建 HTTP API 服务。
  • 掌握 GET、POST、PUT、DELETE 请求。
  • 理解 Python 类型注解、Pydantic 数据校验。
  • 使用 SQLite 实现真正的数据库 CRUD。
  • 学会项目目录组织、异步编程、接口文档和测试。

一、FastAPI 到底是什么?

先看一个概念:

FastAPI 是一个使用 Python 编写的现代 Web API 框架。

如果你以前使用过 Express,那么可以这样理解:

Node.js 生态Python 生态作用
Node.jsPython运行环境
npm / pnpmpip / uv包管理
ExpressFastAPIWeb API 框架
NestJSFastAPI + 分层架构组织后端业务
TypeScriptPython 类型注解类型声明
Zod / class-validatorPydantic数据校验
Prisma / TypeORMSQLModel / SQLAlchemyORM
nodemonfastapi dev开发热重载
SwaggerFastAPI 内置 OpenAPIAPI 文档

FastAPI 有几个非常实用的特点:

  1. 代码简洁: 不需要大量配置就可以创建 API。
  2. 自动参数校验: 请求参数类型不对,框架自动返回错误。
  3. 自动生成 API 文档: 不需要额外安装 Swagger。
  4. 支持 async / await: 可以处理异步 I/O 操作。
  5. 类型提示友好: VS Code、PyCharm 等编辑器可以获得良好的自动补全。

FastAPI 基于 Starlette 和 Pydantic,数据库层不绑定特定 ORM,可以按项目需求选择。

GitHub

+1

二、Express 和 FastAPI 代码对比

先不安装环境,直接看代码。

Node.js + Express

JavaScript


import express from "express";

const app = express();

app.get("/hello", (req, res) => {
  res.json({
    message: "Hello World"
  });
});

app.listen(3000, () => {
  console.log("Server running");
});
  

Python + FastAPI

Python

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

两个框架做的是同一件事:接收 /hello 请求,返回 JSON。

主要区别:

  • Express 通过 app.get() 注册回调。
  • FastAPI 使用 @app.get() 装饰器定义路由。
  • Express 通过 res.json() 返回数据。
  • FastAPI 直接 return Python 字典,框架会自动转换为 JSON。

可以把 @app.get() 理解为 Express 的路由注册语法。

三、搭建 FastAPI 开发环境

这里以 macOS 为例,Windows 和 Linux 的开发流程基本一致。

1. 检查 Python

打开终端:

python3 --version

建议使用 Python 3.12 或更新的稳定版本。本文代码使用 Python 3.10+ 的类型语法。

2. 安装 uv

如果你熟悉 pnpm,那么建议了解一下 uv。

它是一个 Python 项目与依赖管理工具,可以帮助你创建虚拟环境、安装依赖、锁定版本和运行程序。

macOS 使用 Homebrew 安装:

brew install uv

检查:

uv --version

3. 创建项目

直接复制执行:

# 创建 Python 项目
uv init fastapi-demo --bare

# 进入项目
cd fastapi-demo

# 安装 FastAPI 和标准开发依赖
uv add "fastapi[standard]"

# 检查环境
uv run python --version

这和 Node.js 中的以下操作非常相似:

mkdir express-demo
cd express-demo

npm init -y
npm install express

官方也推荐使用 uv 创建项目、管理依赖和运行 FastAPI。

GitHub

+1

4. 认识目录

fastapi-demo/
├── .venv/           # Python 虚拟环境
├── .python-version   # Python 版本(如有)
├── pyproject.toml    # 类似 package.json
├── uv.lock           # 类似 pnpm-lock.yaml
└── main.py           # 程序入口(下一步创建)

其中:

  • pyproject.toml:项目名称、依赖、配置。
  • uv.lock:记录锁定的依赖版本。
  • .venv:项目隔离的 Python 环境。
  • main.py:FastAPI 入口文件。

可以把 .venv 理解为 Node 开发时的项目依赖隔离环境,不过它不等同于 node_modules。

四、创建第一个 FastAPI 服务

在项目根目录创建 main.py:

from fastapi import FastAPIapp = FastAPI(    title="我的第一个 FastAPI 项目",    description="Node.js 开发者学习 FastAPI",    version="1.0.0")@app.get("/")def index():    return {        "code": 200,        "message": "FastAPI 启动成功",        "data": {            "framework": "FastAPI",            "language": "Python"        }    }

运行:

uv run fastapi dev main.py

终端将启动开发服务器,通常访问地址为 http://127.0.0.1:8000。

打开浏览器:

http://127.0.0.1:8000

返回:

{
  "code": 200,
  "message": "FastAPI 启动成功",
  "data": {
    "framework": "FastAPI",
    "language": "Python"
  }
}

FastAPI 最方便的功能:自动生成 API 文档

Swagger UI 接口文档

自动生成

A Close Look at a FastAPI Example Application – Real Python

realpython.com

FastAPI 的 Swagger UI 文档界面示意

http://127.0.0.1:8000/docs

复制地址

启动后可以访问三个地址:

地址用途
/docsSwagger UI,支持在线调试
/redocReDoc API 文档
/openapi.jsonOpenAPI 接口描述

这一点对于开发前后端分离项目很方便。

五、学习 FastAPI 路由

对于写过 Express 的开发者,路由几乎没有学习成本。

1. GET 请求

Express:

app.get("/users", (req, res) => {
  res.json(["张三", "李四"]);
});

FastAPI:

@app.get("/users")def get_users():    return ["张三", "李四"]

2. POST 请求

FastAPI 推荐使用 Pydantic 模型定义请求体:

from pydantic import BaseModelclass UserCreate(BaseModel):    name: str    age: int@app.post("/users")def create_user(user: UserCreate):    return {        "message": "创建成功",        "user": user    }

前端请求:

await fetch("http://127.0.0.1:8000/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    name: "张三",
    age: 25
  })
});

你可以把:

class UserCreate(BaseModel):    name: str    age: int

理解为 TypeScript 的接口类型声明加上运行时的 Zod 数据校验。

当传入:

{
  "name": "张三",
  "age": "abc"
}

FastAPI 会检测到 age 不能解析为整数,并返回 HTTP 422 校验错误。

这意味着很多以前在 Express 中需要手动编写的参数校验逻辑,可以直接交给 Pydantic。

3. 路径参数

Express:

app.get("/users/:id", (req, res) => {
  const id = Number(req.params.id);
  res.json({ id });
});

FastAPI:

@app.get("/users/{id}")def get_user(id: int):    return {"id": id}

访问:

GET /users/100

返回:

{"id": 100}

id: int 表示该参数必须能够解析成整数。

4. Query 查询参数

Express:

app.get("/search", (req, res) => {
  const keyword = req.query.keyword;
  res.json({ keyword });
});

FastAPI:

@app.get("/search")def search(keyword: str = ""):    return {        "keyword": keyword    }

访问:

GET /search?keyword=python

返回:

{"keyword": "python"}

5. PUT 和 DELETE

@app.put("/users/{id}")def update_user(id: int, user: UserCreate):    return {        "id": id,        "user": user    }@app.delete("/users/{id}")def delete_user(id: int):    return {        "message": f"用户 {id} 已删除"    }

到这里你已经掌握 FastAPI 最基本的路由开发。

六、Python 语法:Node.js 开发者只需要先掌握这些

JavaScript / TypeScriptPython
const name = "Tom"name = "Tom"
let age = 20age = 20
function add(a, b) {}def add(a, b):
console.log("Hello")print("Hello")
true / falseTrue / False
nullNone
a === ba == b
!valuenot value
a && ba and b
a || ba or b
array.map(...)列表推导式或 map()
try / catchtry / except
import x from "x"import x / from x import y

Python 使用缩进组织代码

JavaScript:

function getName(name) {
  if (name) {
    return name;
  }
  return "Unknown";
}

Python:

def get_name(name):    if name:        return name    return "Unknown"

Python 没有 {} 包围代码块,而是使用缩进。

建议统一使用四个空格。

Python 类型注解

TypeScript:

function add(a: number, b: number): number {
  return a + b;
}

Python:

def add(a: int, b: int) -> int:    return a + b

需要注意:Python 的类型注解默认不会像 TypeScript 编译器那样进行强制静态检查。 FastAPI 会根据声明的接口参数类型执行验证和转换,而普通 Python 函数则不会自动验证类型。

Python 类

TypeScript:

class User {
  constructor(
    public name: string,
    public age: number
  ) {}
}

Python:

class User:    def __init__(self, name: str, age: int):        self.name = name        self.age = age

self 类似 JavaScript 类中的 this。

理解这些语法后,阅读大部分 FastAPI 入门代码不会太困难。

七、实战:开发一个真正的用户管理 API

前面只是基本路由。接下来我们做一个可以运行的项目。

实现的功能包括:

  • 新增用户
  • 查询用户列表
  • 查询单个用户
  • 修改用户
  • 删除用户
  • SQLite 数据库存储
  • 自动生成接口文档

这相当于一个简化版的 Express + Prisma 用户管理系统。

1. 安装数据库依赖

这里使用 SQLModel。

它结合了 SQLAlchemy 和 Pydantic,既能描述数据库表,也能支持类型校验。FastAPI 官方的 SQL 数据库教程也使用 SQLModel 作为示例。

FastAPI

+1

在刚才的项目目录执行:

uv add sqlmodel

SQLite 是 Python 自带支持的数据库,入门阶段不需要安装 MySQL 或 PostgreSQL。

2. 创建完整项目代码

把 main.py 替换为以下代码。这是一套完整、可运行的 CRUD 示例。

from contextlib import asynccontextmanagerfrom typing import Annotatedfrom fastapi import Depends, FastAPI, HTTPException, Queryfrom pydantic import BaseModel, ConfigDict, Fieldfrom sqlmodel import (    Field as SQLField,    Session,    SQLModel,    create_engine,    select,)# ========== 1. 数据库配置 ==========sqlite_url = "sqlite:///./database.db"engine = create_engine(    sqlite_url,    connect_args={"check_same_thread": False})# ========== 2. 数据库表 ==========class User(SQLModel, table=True):    id: int | None = SQLField(        default=None,        primary_key=True    )    name: str    age: int    email: str

本例为了方便入门,把所有逻辑放在一个文件中。数据库的 email 暂时只验证最小长度,并没有做邮箱格式校验或唯一性约束,后面可以进一步完善。

3. 启动项目

执行:

uv run fastapi dev main.py

第一次启动后,项目目录会新增:

fastapi-demo/
├── .venv/
├── pyproject.toml
├── uv.lock
├── main.py
└── database.db

database.db 就是 SQLite 数据库文件。

4. 测试 CRUD

直接访问:

http://127.0.0.1:8000/docs

也可以使用终端测试。

创建用户


curl -X POST http://127.0.0.1:8000/users \
  -H "Content-Type: application/json" \
  -d '{
    "name": "张三",
    "age": 25,
    "email": "zhangsan@example.com"
  }'
  

预期返回:

{
  "id": 1,
  "name": "张三",
  "age": 25,
  "email": "zhangsan@example.com"
}

继续测试:

查询用户列表


curl http://127.0.0.1:8000/users
  

查询指定用户


curl http://127.0.0.1:8000/users/1
  

修改用户年龄


curl -X PATCH http://127.0.0.1:8000/users/1 \
  -H "Content-Type: application/json" \
  -d '{"age": 26}'
  

删除用户


curl -X DELETE http://127.0.0.1:8000/users/1
  

至此,一个真正将数据保存到数据库中的 REST API 已经完成。

5. 理解数据库代码

如果以前用过 Prisma,这段逻辑应该很好理解。

SQLModel / FastAPIPrisma / Node.js
session.add(user)prisma.user.create() 的部分操作
session.commit()提交数据库事务
session.refresh(user)从数据库刷新对象
session.get(User, id)prisma.user.findUnique()
select(User)prisma.user.findMany()
session.delete(user)prisma.user.delete() 的部分操作

注意,ORM 的接口并不是一一对应。SQLModel 使用显式 Session 管理事务,而 Prisma Client 通常把创建、更新等操作封装成方法调用。

八、理解 Depends:FastAPI 的依赖注入

你可能注意到代码里有:

SessionDep = Annotated[    Session,    Depends(get_session)]

这是什么?

可以把它理解成:每次请求进入路由时,FastAPI 自动准备一个数据库 Session,路由执行结束后再关闭它。

一次请求中的数据库依赖生命周期

在 Express 中,我们可能手动获取数据库连接并释放:

app.get("/users", async (req, res) => {
  const users = await prisma.user.findMany();
  res.json(users);
});

在 FastAPI 中,常见写法是:

@app.get("/users")def get_users(session: SessionDep):    return session.exec(select(User)).all()

不必在每个路由中重复编写创建和关闭 Session 的代码。

Depends() 不只用于数据库,也可以管理:

  • JWT 用户认证
  • 登录权限判断
  • 配置读取
  • 公共参数处理
  • 服务对象注入

它在 FastAPI 中非常重要。

九、async / await:和 Node.js 有什么区别?

对于 Node.js 开发者,这也是必须理解的部分。

Node.js 异步代码

async function getUser() {
  const response = await fetch(
    "https://example.com/api/user"
  );

  return await response.json();
}

FastAPI 异步代码

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

需要先安装:

uv add httpx

这里的 https://example.com/api/user 是演示地址,并不是可用的真实 API。

两者的 async / await 编写体验相似,但运行时机制并不完全相同。

什么时候用 async def?

场景建议
异步 HTTP 请求async def
异步数据库驱动async def
WebSocketasync def
同步 SQLModel Session普通 def
同步文件库或同步 SDK通常使用普通 def
大量 CPU 密集计算独立进程或任务执行器

重要:不是所有 FastAPI 路由都应该写成 async def。

FastAPI 可以把普通同步路由放在线程池执行。对于同步数据库调用,通常使用 def 更合适。

如果在 async def 路由中直接执行长时间的同步阻塞操作,反而可能阻塞事件循环。

十、配置跨域 CORS

你以前使用 Vue、React 调用 Express API 时,应该用过 cors。

Express:

import cors from "cors";

app.use(cors({
  origin: ["http://localhost:5173"]
}));

FastAPI:

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

把这段代码放到创建 app 后的位置即可。

这样就允许本地 Vite 前端从 http://localhost:5173 访问 FastAPI。

生产环境应配置实际允许的前端域名,不要随意开放所有来源。

十一、实际开发应该怎样组织目录?

前面我们将路由、数据库、业务代码全部放进 main.py,方便学习,但真正开发时不建议这样组织。

如果你熟悉 NestJS,可以直接采用类似的模块化目录。

推荐的 FastAPI 项目结构


fastapi-demo/
├── app/
│   ├── __init__.py
│   ├── main.py
│   │
│   ├── api/
│   │   ├── __init__.py
│   │   └── users.py
│   │
│   ├── models/
│   │   ├── __init__.py
│   │   └── user.py
│   │
│   ├── schemas/
│   │   ├── __init__.py
│   │   └── user.py
│   │
│   ├── services/
│   │   ├── __init__.py
│   │   └── user_service.py
│   │
│   ├── repositories/
│   │   ├── __init__.py
│   │   └── user_repository.py
│   │
│   ├── core/
│   │   └── config.py
│   │
│   └── db/
│       └── database.py
│
├── tests/
│   └── test_users.py
│
├── .env
├── .gitignore
├── pyproject.toml
└── uv.lock

对应 NestJS:

FastAPINestJS职责
main.pymain.ts程序入口
api/users.pyusers.controller.ts路由
services/*.service.ts业务逻辑
repositories/Repository数据访问
schemas/dto/请求、响应校验
models/entities/数据库实体
core/config.pyConfigModule环境配置
Depends()依赖注入机制注入依赖

APIRouter:类似 Express Router

例如 app/api/users.py:

from fastapi import APIRouterrouter = APIRouter(    prefix="/users",    tags=["用户管理"])@router.get("/")def get_users():    return [        {"id": 1, "name": "张三"},        {"id": 2, "name": "李四"}    ]

在 app/main.py 中注册:

from fastapi import FastAPIfrom app.api.users import router as users_routerapp = FastAPI()app.include_router(users_router)

启动:

uv run fastapi dev app/main.py

这样你就把路由模块单独拆分出来了。

更大型的项目可以继续分成 Controller(API 层)、Service(业务层)、Repository(数据访问层)。

不过 FastAPI 没有要求你必须遵守 NestJS 的分层模式,简单项目不必过度设计。

十二、FastAPI 怎么写接口测试?

熟悉 Node.js 的你可能使用过 Jest、Vitest 或 Supertest。

Python 生态里可以使用 pytest,FastAPI 还提供了方便的 TestClient。

先安装:

uv add --dev pytest

创建 test_main.py:

from fastapi import FastAPIfrom fastapi.testclient import TestClientapp = FastAPI()@app.get("/hello")def hello():    return {"message": "Hello"}client = TestClient(app)def test_hello():    response = client.get("/hello")    assert response.status_code == 200    assert response.json() == {        "message": "Hello"    }

执行:

uv run pytest -v

这个例子用于学习 HTTP 接口断言。实际项目中应该从应用模块导入 app,并为 CRUD 测试准备独立的测试数据库,避免影响开发数据。

十三、常用命令速查

建议收藏这张表,以后开发时经常会用到。

Node.jsPython + uv
npm init -yuv init --bare
npm install expressuv add "fastapi[standard]"
npm install axiosuv add httpx
npm install -D vitestuv add --dev pytest
npm uninstall axiosuv remove httpx
npm installuv sync
npm run devuv run fastapi dev main.py
npm testuv run pytest
node app.jsuv run python app.py

生产环境可以使用:

uv run fastapi run main.py

这是生产运行模式,但真实部署时还需要配置反向代理、HTTPS、进程管理、日志、数据库迁移和健康检查等。

十四、FastAPI、Express、NestJS,究竟怎么选?

对比ExpressNestJSFastAPI
语言JavaScript / TSTypeScriptPython
学习成本低中低至中
项目结构自由规范化自由
类型校验需要额外方案DTO 等方案Pydantic
Swagger通常需要配置需要集成自动生成
AI / ML 生态可以集成可以集成Python 生态优势明显
大型业务系统可以适合可以
异步 I/O支持支持支持

对于你这种已经有 Node.js 开发经验的程序员,我建议:

如果是常规企业后台、业务系统和已经成熟的 TypeScript 技术栈,继续使用 NestJS 没问题。

如果要开发 AI Agent、RAG 知识库、Ollama 模型接口、数据处理或者机器学习服务,FastAPI 值得优先学习。

不是 FastAPI 天生比 NestJS 更适合所有后端业务,而是 Python 的 AI 相关工具链非常丰富,可以减少跨语言调用的成本。

十五、实战进阶:FastAPI + Ollama

例如,你希望用 FastAPI 包装一个本地模型接口,让 React、Vue 或其他 Agent 应用统一调用。

假设你的本机已启动 Ollama,并已经下载了一个可用模型,就可以采用下面这种架构:

FastAPI 作为本地 AI 服务的 HTTP 接口层

安装 HTTP 客户端:

uv add httpx

创建 ai_server.py:

import httpxfrom fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModelapp = FastAPI(title="本地 AI 服务")class ChatRequest(BaseModel):    message: str    model: str@app.post("/chat")async def chat(payload: ChatRequest):    try:        async with httpx.AsyncClient(            timeout=120        ) as client:            response = await client.post(                "http://127.0.0.1:11434/api/chat",                json={                    "model": payload.model,                    "messages": [                        {                            "role": "user",                            "content": payload.message                        }                    ],                    "stream": False                }            )            response.raise_for_status()

启动:

uv run fastapi dev ai_server.py

调用:

curl -X POST http://127.0.0.1:8000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "介绍一下 FastAPI",
    "model": "llama3.2"
  }'

这里的 llama3.2 只是示例模型名称,必须先通过 ollama list 确认本机存在对应模型。这个示例采用非流式输出,方便理解;后续可以改成 SSE 流式响应。

实际对外部署时,还需要增加用户认证、模型白名单、超时控制和限流等安全机制。

十六、建议学习路线

如果目标是从 Node.js 转向 FastAPI 开发,可以按下面的顺序学习。

FastAPI 学习进度

0 / 6 已完成

第 1 阶段:Python 基础

变量、函数、类、类型注解、异常、async/await

第 2 阶段:FastAPI 基础

路由、请求参数、Pydantic、HTTP 错误、Swagger

第 3 阶段:数据库

SQLite、PostgreSQL、SQLModel、SQLAlchemy、事务

第 4 阶段:工程化

APIRouter、Depends、环境配置、pytest、Alembic 迁移

第 5 阶段:权限与部署

JWT、用户权限、Docker、Nginx、日志、监控

第 6 阶段:AI 项目实战

FastAPI + Ollama + RAG + Agent + SSE 流式响应

十七、推荐的官方学习资料

总结

作为 Node.js 开发者,你可以记住下面五句话:

  1. FastAPI 类似 Express,但更强调 Python 类型注解和自动数据校验。
  2. Pydantic 可以理解为 Python 中的 DTO + Zod。
  3. SQLModel 可以理解为 Python 生态中的 ORM 工具之一。
  4. Depends 是 FastAPI 很重要的依赖注入机制。
  5. uv 可以作为 Python 项目中类似 pnpm 的依赖和运行管理工具。

你已经具备 HTTP、REST API、数据库、异步编程等后端开发基础,不需要从零重新学习后端设计。主要需要适应 Python 语法、Pydantic、依赖注入以及 Python 的运行和包管理方式。