FastAPI项目刚开始的时候,一个main.py完全够用。
比如:
main.py里面放:
app = FastAPI()
@app.get("/")
def index():
...
@app.get("/users")
def users():
...
@app.post("/login")
def login():
...刚开始开发的时候很舒服。
但功能一多,main.py很快就变成几百上千行。
这时候就得开始拆项目了。
一个简单的结构
我比较推荐从简单的结构开始:
app/
├── main.py
├── routers/
│ ├── users.py
│ └── auth.py
├── services/
│ ├── user.py
│ └── auth.py
├── database/
│ └── db.py
└── schemas/
└── user.py不一定所有项目都需要这么全。
但这种结构比较好理解。
Router
Router负责处理HTTP层。
比如:
@router.get("/users/{user_id}")
def get_user(user_id: int):
...Router主要关心:
- URL
- HTTP Method
- 参数
- 返回值
- 权限依赖
不应该把大量业务逻辑塞进去。
Service
Service负责业务逻辑。
比如:
def create_user(username, email):
# 检查用户名
# 创建用户
# 保存数据库
# 返回结果Router:
@router.post("/users")
def create_user(data: UserCreate):
return user_service.create_user(data)这样HTTP层和业务逻辑就分开了。
Database
数据库层负责和数据库打交道。
比如:
def find_user(db, username):
cursor = db.cursor()
cursor.execute(
"SELECT * FROM users WHERE username = ?",
(username,)
)
return cursor.fetchone()Service不用关心SQL具体怎么写。
它只需要知道:
find_user()能找到用户。
Schema
Schema主要用来描述API数据结构。
比如:
from pydantic import BaseModel
class UserCreate(BaseModel):
username: str
email: strAPI:
@router.post("/users")
def create_user(data: UserCreate):
...这样客户端提交的数据就有明确结构了。
为什么需要分层
假设所有代码都写在一个函数里:
def create_user(data):
# 参数检查
# 用户是否存在
# 密码处理
# SQL
# 日志
# 返回结果代码一多,改什么都费劲。
拆分之后:
Router
↓
Service
↓
Database每层管自己的事。
以后要换数据库,或者改业务逻辑,就不会牵一发动全身。
但别为了分层而分层
这也是我实际开发里比较在意的一点。
如果只有:
3个API
1张表
100行代码却搞出:
controller
service
repository
factory
provider
adapter
entity其实没必要。
好的架构不是"层越多越好"。
而是:
复杂度增加的时候,再加能真正解决问题的抽象。
一个实际开发思路
我更倾向按下面的过程走:
第一步:先让功能跑起来
FastAPI
↓
SQLite先把API写出来。
第二步:发现重复代码
比如数据库连接到处重复。
于是抽出:
database/第三步:业务开始复杂
于是抽出:
services/第四步:API数量增加
于是按功能拆:
routers/
├── users.py
├── auth.py
└── settings.py这种方式比一开始就设计一个巨复杂的企业级架构实用得多。
FastAPI项目最终可以长成这样
app/
├── main.py
│
├── routers/
│ ├── users.py
│ └── auth.py
│
├── services/
│ ├── user.py
│ └── auth.py
│
├── database/
│ └── db.py
│
└── schemas/
├── user.py
└── auth.py数据流大概是:
HTTP Request
↓
Router
↓
Service
↓
Database
↓
SQLite这套结构不复杂,但已经够支撑一个比较正常的个人后端项目了。
总结
FastAPI本身已经提供了很好的开发体验。
真正进入项目之后,需要解决的不再只是:
"这个接口怎么写?"
而是:
"这个项目以后怎么维护?"
从数据库连接、Session,到Router、Service和数据层,其实都是在解决同一个问题:
让代码随着项目增长,依然能保持清晰。
到这里,FastAPI基础后端部分已经开始从"写接口"进入"设计项目"了。
下一阶段就可以往Linux、Nginx、部署和服务器方向走,让本地跑的FastAPI变成一个能长期运行的服务。