惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX - 技术
D
DataBreaches.Net
阮一峰的网络日志
阮一峰的网络日志
Recent Announcements
Recent Announcements
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
T
The Exploit Database - CXSecurity.com
Simon Willison's Weblog
Simon Willison's Weblog
Cisco Talos Blog
Cisco Talos Blog
Microsoft Security Blog
Microsoft Security Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
K
Kaspersky official blog
F
Fortinet All Blogs
GbyAI
GbyAI
Forbes - Security
Forbes - Security
The Cloudflare Blog
博客园 - 司徒正美
博客园_首页
量子位
Schneier on Security
Schneier on Security
G
GRAHAM CLULEY
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
P
Proofpoint News Feed
N
News | PayPal Newsroom
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
T
Tor Project blog
V
Vulnerabilities – Threatpost
Y
Y Combinator Blog
Jina AI
Jina AI
Help Net Security
Help Net Security
T
Threat Research - Cisco Blogs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
Cybersecurity and Infrastructure Security Agency CISA
Project Zero
Project Zero
N
News and Events Feed by Topic
I
Intezer
B
Blog
美团技术团队
C
CERT Recently Published Vulnerability Notes
NISL@THU
NISL@THU
L
LINUX DO - 最新话题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
AWS News Blog
AWS News Blog
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
雷峰网
雷峰网
有赞技术团队
有赞技术团队

windsong

从画图纸到捏泥巴:从后端到 JavaScript 清华校园网认证笔记 摆脱“被动焦虑”的终极解药:一个尼采主义者的自我救赎与“强力意志”觉醒 windsong Vue 组件通信 词法作用域与动态作用域 Pinia Store :前端的 MVVM 解耦 前后端交互的桥梁:Axios 全栈容器化应用的环境变量管理 早抛晚捕:异常处理 股票市场常识 大噜村的债务:过去和未来 大噜村的发展故事 重读设计模式:从理论到实践的反思(二) Transformer 个人入门 Go Viper:设计哲学与最佳实践 简单的 Go WebSocket 服务器 最简单的 Go HTTP 服务器 Go 语言核心机制:命名类型与接口
全栈架构:三套 Schema
xxxx · 2026-01-10 · via windsong

全栈架构:三套 Schema

在一个数据驱动的全栈系统中,最核心的工作流莫过于:前端发送请求 -> 后端处理逻辑 -> 读写数据库 -> 数据返回前端

在这个过程中,同一个业务实体(比如一只“动物”或一朵“花”),虽然代表的信息是一致的,但在不同的系统层级中,其表现形式(Schema)承载的职责是截然不同的。

通常,一个规范的全栈项目需要维护“三套 Schema”:

  1. Database Schema:用于数据库存储(ORM 模型)。
  2. API Schema:用于后端接口的数据验证与序列化(Pydantic 模型)。
  3. Frontend Schema:用于前端页面的类型检查与展示(TypeScript 接口)。

以 Python (FastAPI/SQLAlchemy) + Frontend (TypeScript) 为例,梳理这三套 Schema 的定义与协作。

第一套:Database Schema (ORM Layer)

数据库层是数据的源头。在 Python 后端中,我们通常使用 SQLAlchemy 这样的 ORM(对象关系映射)库,将数据库表结构映射为 Python 类。通常在 backend/app/db 目录下维护数据库连接逻辑。

  • Engine: 负责与数据库的实际通信。
  • Session: 数据库会话,相当于一个“连接句柄”,用于执行 CRUD 操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from app.core.config import settings



engine = create_engine(settings.DATABASE_URL, pool_pre_ping=True)



SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db() -> Session:
"""
依赖注入工具函数:
每个请求创建一个独立的 Session,请求结束后自动关闭
"""
db = SessionLocal()
try:
yield db
finally:
db.close()

backend/models 中定义表结构。所有模型继承自 SQLAlchemy 的 Base 类。

1
2
3
4
5
6
7
8
9
10
from sqlalchemy import Column, Integer, String, Date, Float
from app.db.base_class import Base

class Animal(Base):
__tablename__ = "animals"

id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
acquire_date = Column(Date, nullable=False)

这一层 Schema 的核心职责:精确描述数据库表的结构(字段类型、主键、外键、索引),直接对应 SQL 语句。

第二套:API Schema (Pydantic Layer)

这是后端与外界交互的“关口”,在 FastAPI 中,我们使用 Pydantic 来定义这套 Schema。通常位于 backend/app/schemas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional
from datetime import date, datetime


class AnimalBase(BaseModel):
name: str = Field(..., min_length=1, max_length=100, description="动物名称")
quantity: int = Field(..., ge=0, description="数量")
acquire_date: date = Field(..., description="购入/出生日期")
notes: Optional[str] = Field(None, max_length=500, description="备注")


class AnimalCreate(AnimalBase):
pass


class AnimalResponse(AnimalBase):
id: int
created_at: datetime
updated_at: datetime


model_config = ConfigDict(from_attributes=True)

默认情况下,Pydantic 只能读取字典(如 data['id'])。开启 from_attributes=True 后 ,Pydantic 可以读取对象属性(如 data.id)。此时我们可以直接把 SQLAlchemy 返回的数据库对象扔给 Pydantic,它能自动提取数据。

在 API 中使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@router.post("/", response_model=AnimalResponse, status_code=201)
def create_animal(
animal_data: AnimalCreate,
db: Session = Depends(get_db)
):

db_animal = Animal(**animal_data.model_dump())

db.add(db_animal)
db.commit()
db.refresh(db_animal)


return db_animal

我们在这里直接 return 了一个 SQLAlchemy 的表结构类,它自动转换成了 AnimalResponse,这是 FastAPI 的强大功能之一。虽然函数 return db_animal 返回的是一个 ORM 对象,但装饰器中的 response_model=AnimalResponse 会介入。FastAPI 会利用 Pydantic 的 from_attributes=True 特性,从 db_animal 中提取字段,过滤掉未在 AnimalResponse 中定义的字段,并将数据序列化为 JSON 返回给前端。

第三套:Frontend Schema (TypeScript Layer)

数据流出后端后,前端也需要一套标准来“接住”这些数据。在 TypeScript 项目中,我们在 src/types 中定义 Interface。

这一层定义应与后端的 Pydantic Schema 保持一一对应。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

export interface Animal {
id: number
name: string
quantity: number
acquire_date: string
notes: string | null
created_at: string
updated_at: string
}


export interface AnimalCreate {
name: string
quantity: number
acquire_date: string
notes?: string
}

为什么需要 TypeScript 接口?因为在 JavaScript 中,写 user.nmae (拼写错误) 只有在运行时才会报错。而在 TypeScript 中,因为有了 Interface 充当“模具”,编辑器会在敲代码的那一刻就标红报错,极大地提高了开发效率和安全性。

前端通过 Axios 发送请求时,泛型(Generics)能发挥巨大作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { apiClient } from './client'

export const animalsApi = {

create: async (data: AnimalCreate): Promise<Animal> => {

const response = await apiClient.post<Animal>('/animals', data)
return response.data
},

getList: async (): Promise<Animal[]> => {
const response = await apiClient.get<Animal[]>('/animals')
return response.data
}
}

总结:三套 Schema 的协作流

让我们看一个完整的“创建动物”流程,数据是如何变形的:

  1. 前端 (TypeScript): 用户填写表单,数据符合 AnimalCreate 接口。前端发送 JSON。
  2. 后端入口 (Pydantic): FastAPI 接收 JSON,使用 AnimalCreate (Pydantic) 进行校验(比如数量不能小于0)。
  3. 后端处理 (ORM): 校验通过的数据被转换为 Animal (SQLAlchemy) 模型,写入数据库表。
  4. 后端出口 (Pydantic): 数据库返回的 ORM 对象,被 AnimalResponse (Pydantic) 过滤和序列化,变回 JSON。
  5. 前端接收 (TypeScript): 前端收到 JSON,将其识别为 Animal 接口类型,渲染到列表中。

这三套 Schema 分别守护了数据库的完整性API 的安全性前端的类型安全。在大型系统中,这种分层架构是保持代码清晰、可维护的基石。