数据库项目如何进行分层设计?

在一个后端项目中,数据库相关代码需要进行合理分层,避免模型定义、数据库连接、业务操作全部混杂在一起。

一个推荐的结构如下:

1
2
3
4
5
6
7
8
9
10
src/
├── models/
│ ├── __init__.py
│ ├── base.py
│ └── user.py

├── db/
│ └── crud.py

└── database.py

一、models 层:负责数据库模型定义

models 目录主要负责定义数据库中的表结构。

目录结构

1
2
3
4
5
/src/models

- __init__.py
- base.py
- user.py

1. init.py

__init__.py 的作用是初始化模型模块。

例如:

1
from src.models.user import UserModel

为什么需要提前导入模型?

因为 SQLAlchemy 在执行:

1
Base.metadata.create_all(bind=engine)

时,需要提前知道有哪些模型存在。

如果没有导入对应的模型文件,Base 可能不知道有哪些数据表需要创建,最终导致数据库初始化时无法生成对应表。

所以:

init.py 的作用就是提前加载并注册所有模型,让 SQLAlchemy 能够识别完整的表结构。


2. base.py

base.py 负责定义所有模型的基类。

例如:

1
2
3
4
5
from sqlalchemy.orm import DeclarativeBase


class Base(DeclarativeBase):
pass

所有数据库模型都会继承这个 Base

例如:

1
2
class UserModel(Base):
...

这样做的好处:

  • 统一管理所有模型
  • 方便 SQLAlchemy 创建数据表
  • 降低模型之间的耦合

3. user.py

user.py 负责具体的数据表定义。

例如:

1
2
3
4
5
class UserModel(Base):
__tablename__ = "users"

id = Column(...)
username = Column(...)

每一个模型文件对应数据库中的一张表。


二、db 层:负责数据库操作

目录:

1
2
3
/src/db

- crud.py

crud.py 主要负责数据库的增删改查操作。

例如:

  • 创建用户
  • 查询用户
  • 修改用户信息
  • 删除用户

需要注意:

crud 层只负责数据库 CRUD,不应该包含业务逻辑。

例如:

错误:

1
2
3
create_user()
检查用户权限()
发送邮件()

正确:

1
2
3
4
create_user()
get_user()
update_user()
delete_user()

业务逻辑应该交给 service 层处理。


三、database.py:负责数据库连接管理

database.py 是数据库连接的核心文件。

它主要暴露两个功能:

  1. 初始化数据库
  2. 提供数据库 Session

1. 创建数据库连接

1
2
3
4
5
6
7
8
9
10
11
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from src.config import settings

from src.models.base import Base


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

这里导入:

1
from src.models.base import Base

非常重要。

它会触发 models 包加载,使 SQLAlchemy 提前知道有哪些模型。


2. 创建 Session 工厂

1
2
3
4
5
SessionLocal = sessionmaker(
bind=engine,
autoflush=False,
expire_on_commit=False,
)

SessionLocal 用于创建数据库会话。

每一次数据库操作,都需要通过 Session 与数据库交互。


3. 初始化数据库

1
2
3
4
5
def init_db():

Base.metadata.create_all(
bind=engine
)

这个函数通常会在 FastAPI 启动时调用。

作用:

  • 创建不存在的数据表
  • 初始化数据库结构

4. 提供数据库 Session

1
2
3
4
5
6
7
8
9
def get_db():

db = SessionLocal()

try:
yield db

finally:
db.close()

这个函数主要给 FastAPI 的依赖注入使用。

流程:

1
2
3
4
5
6
7
8
9
请求进入

创建 Session

CRUD 操作数据库

请求结束

关闭 Session

这样可以保证数据库连接及时释放。


总结:各层职责

文件 职责
models/ 定义数据库表结构
models/base.py 提供 ORM 基类
models/init.py 注册所有模型
models/user.py 定义具体表
db/crud.py 负责数据库增删改查
database.py 管理数据库连接和 Session

整体设计思想:

模型负责描述数据,crud 负责操作数据,database.py 负责管理连接。

通过这种分层方式,可以让数据库代码更加清晰,方便后期扩展和维护。


本站由 楠瓜 使用 Stellar 1.33.1 主题创建。
风起于青萍之末,浪成于微澜之间。