FastAPI-Web项目的model、schema、services和视图函数文件之间的关系

对于基于FastAPI框架的web项目而言,我们总能在app文件里看见models / schemas / services / 视图函数(routers / controllers)这样不同名字的文件夹, 这是FastAPI + SQLAlchemy + Pydantic 的典型目录结构。

下面用 FastAPI + SQLAlchemy + Pydantic 的典型目录结构来说明四个层次——models / schemas / services / 视图函数(routers / controllers)——各自职责与数据流向。逻辑同样适用于 Django、Flask‐SQLAlchemy、NestJS 等分层思想,只是命名略有不同。

1. models(持久化/数据库层)

关键点说明
作用映射数据库表,负责 持久化:增删改查(ORM 操作)、表结构定义。
技术SQLAlchemy DeclarativeBase、Django ORM、GORM 等。
只关心字段类型、索引、外键、关系映射(relationship)、事务。
不做数据校验(业务层面)、序列化给前端等。

class User(Base):         # SQLAlchemy
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, index=True)
    hashed_password = Column(String)
    is_active = Column(Boolean, default=True)

2. schemas(Pydantic 模型/序列化层)

关键点说明
作用输入输出的契约:请求体反序列化、响应体序列化、字段校验;与数据库解耦。
技术Pydantic BaseModel、Marshmallow、DRF Serializer。
只关心字段格式、校验规则、默认值、嵌套模型、OpenAPI 文档。
不做直接操作数据库、业务计算。

class UserCreate(BaseModel):
    email: EmailStr
    password: constr(min_length=8)  # 仅限创建时出现

class UserOut(BaseModel):
    id: int
    email: EmailStr
    is_active: bool

优点

  • 安全:不把数据库的敏感字段(如 hashed_password)暴露给前端。

  • 解耦:数据库换成 MongoDB,只改 models 和 services,schema 不变。

  • 文档:Pydantic → FastAPI 自动生成 Swagger/OpenAPI。

3. services(业务逻辑层 / service layer)

关键点说明
作用业务规则 + 复用:聚合多个 model、封装事务、第三方调用、复杂计算。
技术普通 Python 模块 / 类,偶尔搭配 DDD 的 Domain Service
只关心业务流程与边界:如“注册用户”= 判重 → Hash 密码 → 写库 → 发送邮件。
不做HTTP 解析 / 响应、页面渲染。

class UserService:
    @staticmethod
    def create_user(db: Session, obj_in: UserCreate) -> User:
        if db.query(User).filter(User.email == obj_in.email).first():
            raise DuplicateEmailError
        hashed = hash_password(obj_in.password)
        user = User(email=obj_in.email, hashed_password=hashed)
        db.add(user); db.commit(); db.refresh(user)
        return user

4. 视图函数 / controllers / routers(接口层)

关键点说明
作用HTTP → 业务 的粘合剂:解析请求、调用 service、返回响应。
技术FastAPI APIRouter, Flask view function, Django ViewSet。
只关心路由、权限、依赖注入、HTTP 状态码、错误转换。
不做ORM 细节、复杂业务;这些交给 service。

router = APIRouter()

@router.post("/users/", response_model=UserOut, status_code=201)
def create_user(
    user_in: UserCreate,
    db: Session = Depends(get_db),
):
    user = UserService.create_user(db, user_in)
    return user      # Pydantic 自动序列化为 JSON

层与层之间如何协作?



HTTP 请求                数据流 →
┌────────────┐
│ 前端/客户端 │
└─────┬──────┘
      │ JSON (UserCreate)
┌─────▼──────┐
│ 视图函数   │ 依赖注入 / 路由匹配
└─────┬──────┘
      │ Pydantic 校验完的 UserCreate
┌─────▼──────┐
│ Service    │ 业务流程、跨模型操作
└─────┬──────┘
      │ ORM Entity / Query
┌─────▼──────┐
│ Models     │ SQLAlchemy CRUD
└─────┬──────┘
      │ DB Driver
┌─────▼──────┐
│ 数据库      │
└────────────┘

  1. 视图函数 把 JSON → UserCreate (schema),然后交给 services

  2. services 操作 models(ORM),返回 User 对象。

  3. 视图函数再用 UserOut (schema) 把 ORM 对象 → JSON,返回给客户端。


为什么要分层?

目的带来的好处
单一职责每层只管一件事,逻辑更清晰,易维护。
可测试性service 层可写纯单元测试,视图函数只测路由/权限。
解耦/复用改数据库、不走 HTTP 改成 CLI,service 层几乎不动。
安全schema 隔离敏感字段,防止“过度暴露”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值