1 概述
- 之前也使用过 django + django-rest-framework 进行开发,但我始终感觉代码写的不流畅;后来使用 fastapi ,有了一种豁然开朗的感觉。
代码组织架构
- 采用分层架构,有助于解耦业务逻辑,便于维护和扩展;
- 核心理念是将代码按职责划分,每一层只依赖于下一层;
分层架构
- crud 可以定义一个通用库,避免代码重复;
api 接口层
- 结合 Pydantic,用 Pydantic DTO 定义基础类型和部分格式校验;
service 逻辑层
- 实现与「业务用例」强相关的校验逻辑,包括跨字段依赖、业务场景校验等;
model 模型层
- 保持对数据库列的映射和基础约束(类型、非空、长度、外键等),不必承担复杂业务规则。
2 fastapi 项目组织结构
- 目录结构:
├── apps # 应用模块
│ ├── auth # auth 应用模块
│ │ ├── router # 路由接口模块
│ │ └── service # service 模块,与接口模块逻辑分离
│ ├── cmdb
│ │ ├── router
│ │ └── service
│ ├── findata
│ │ ├── router
│ │ └── service
│ ├── task
│ │ ├── router
│ │ └── service
│ └── third
│ ├── router
│ └── service
├── config # 配置文件
├── core # 核心模块,比如项目所需的通用 crud.py
│ └── security
├── data # 数据模块,目前主要存储了测试环境的 sqlite 数据库
├── logs # 日志目录
├── scripts # 项目所需的脚本目录
├── static
└── utils # 工具库模块,主要是外部一些工具库
2.1 目录结构说明
- 参看上方备注;
2.2 其他要点
- 建议每个业务模块使用单独的目录,比如 auth、cmdb、findata、task、third 等;通过配置文件决定 fastapi 加载哪些业务模块;
- crud 建议使用全局的 crud.py,避免重复代码;个别业务需要复杂
sql
,可以在 service 目录单独实现; - config 目录可以配置一个
.env
文件,用于区分 prod 和 dev 环境;- 配置文件格式建议使用
yaml
格式,与编程语言进行解耦; - 可以使用多个配置文件,比如
base.yaml
和prod.yaml
等;
- 配置文件格式建议使用
- 每个 fastapi 项目建议使用项目目录下的
.venv
目录,用于隔离项目依赖; - 服务可以使用
systemd
进行进程管理;
# ln -s /opt/xops/config/xops.service /etc/systemd/system/xops.service
[Unit]
Description=xops service develop with fastapi
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/opt/xops
ExecStart=/opt/xops/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 18000 --workers 8 --log-config config/uvicorn.json
ExecStop=/bin/kill -s TERM $MAINPID
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
3 fastapi 常用工具库推荐
优先使用 github 中 star 多的工具库;
- orm : sqlalchemy
- 身份验证 authentication : passlib + jose
- 授权控制 Authorization : casbin
- 异步任务 : celery + redis
- 部署接口 : ansible-runner
4 前后端对接
- 关于路由实现机制,目前共有三种方案可以选择:
- 前端模式:菜单是“写死”在前端代码里的。只要项目不是一个纯粹的静态展示网站,不建议选择。
- 后端模式:菜单本身是作为一种“数据”存在的,可以需要将菜单图标等非前端数据在后端进行管理。
- 混合模式:前端维护路由定义,后端只下发权限。此方式可以保证前后端项目的独立性;这种方式既保证了前端路由的完整性和开发便利性,又将权限控制的“金钥匙”牢牢地掌握在后端手中,是一种非常健壮和灵活的实践。
- 在前端每一个路由中带有一个元信息(meta)用于和后端接口中的 permissionKey 进行关联;
- 后端返回该用户拥有的权限标识符列表;
- mixed 模式一般实现的功能:
- 动态权限控制: 后端动态返回当前用户拥有的权限码(如按钮权限、接口权限、菜单权限标识)
- 前端本地路由配置: 路由的路径、组件、菜单标题、图标等由前端静态定义,保证界面展示统一且开发效率高。
- 权限码与路由菜单过滤结合: 前端通过后端返回的权限码,过滤本地路由中对应的菜单和功能。
- 按钮级别权限控制: 在页面按钮、操作权限(例如编辑、删除、导出等)上,前端根据权限码控制按钮是否显示或是否可点击。