Skip to content

如何组织一个 FastAPI 项目(搬运)

FastAPI 是一个基于 Python 的高性能 Web 框架,具有类型注解和自动文档功能。

一个良好的项目结构能够帮助我们更好地管理代码,理清思路,并且使项目更容易扩展和维护。

主要文件和目录结构

bash
.
├── app // 主目录
   ├── api // 路由定义
   ├── __init__.py
   └── v1
       ├── __init__.py
       └── endpoints.py
   ├── core common // 数据库连接,安全机制和一些通用的工具函数等
   ├── __init__.py
   ├── config.py
   ├── database.py
   ├── security.py
   └── utils.py
   ├── models // 存放模型的定义,每个模型定义一个 Python 文件
   ├── __init__.py
   └── user.py
   ├── services // 存放业务逻辑的代码,按照模型或功能划分
   ├── __init__.py
   └── user_service.py
   ├── __init__.py
   ├── main.py // 应用入口文件,定义应用的启动逻辑
   └── settings.py
└── tests // 测试代码,按照功能或模块划分子目录
    ├── __init__.py
    ├── conftest.py
    └── end_to_end
        ├── __init__.py
        └── test_endpoints.py

其中,app 目录是整个项目的主目录,tests 目录是用于存放测试代码的目录。

  • app 目录下有以下几个子目录和文件:
    • api 目录用于存放  API 相关的代码,比如不同版本的路由定义和视图函数等。
    • core 目录用于存放核心代码,比如配置文件、数据库连接、安全机制和一些通用的工具函数等。
    • models 目录用于存放数据模型的定义,每个模型定义一个 Python 文件。
    • services 目录用于存放业务逻辑的代码,按照模型或功能划分。
    • main.py 是  FastAPI 应用的入口文件,定义了应用的启动逻辑。
    • settings.py 是存放应用配置的文件。
  • tests 目录是用于存放测试代码的目录,按照功能或模块划分子目录。conftest.py 是存放测试配置和共享的测试数据的文件。

使用模块化的路由结构

为了使路由定义更加清晰和容易维护,我们可以按照模块化的方式组织路由。在上面的项目结构中,api 目录下的每个子目录对应一个 API 版本,比如 v1 目录对应的是 v1 版本的 API。每个版本目录下的 endpoints.py 文件存放该版本下的具体路由定义和视图函数。

以下是一个示例的 endpoints.py 文件:

python
from fastapi import APIRouter

router = APIRouter()


@router.get("/")
async def read_root():
    return {"Hello": "World"}


@router.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

这样的结构可以使路由定义和对应的功能模块解耦,提高代码的可读性和可维护性。

使用依赖注入进行组件管理

FastAPI 支持使用依赖注入来管理组件之间的依赖关系,这可以使代码更加模块化和可测试。我们可以使用 Python 的标准库 typing 来进行类型注解,并在需要的时候将组件注入到视图函数中。

以下是一个使用依赖注入的示例:

python
from fastapi import Depends, FastAPI
from app.services.user_service import UserService

app = FastAPI()


def get_user_service():
    return UserService()


@app.get("/users/{user_id}")
async def read_user(user_id: int, service: UserService = Depends(get_user_service)):
    return service.get_user_by_id(user_id)

在上面的例子中,UserService 是一个服务组件,通过 get_user_service 函数创建实例,然后在 read_user 视图函数中使用 Depends 来注入该实例。这样做可以使我们的代码更加解耦和灵活。

分层架构的设计

FastAPI 使用的是 Model-Controller-Service (MCS) 软件架构模式,这一架构可以提高软件的可维护性和可拓展性。在这种架构下,后端的代码被分成了三部分,每部分都有自己的目标。

  • 控制层 (Controller):负责定义路由,接收请求和返回响应,将请求转发给业务逻辑层进行处理。
  • 业务逻辑层 (Service):负责处理业务逻辑和规则,定义各种业务操作的接口。
  • 数据访问层 (Models):负责与数据库的交互,包括数据持久化和查询等操作。

MCS架构

权限和安全性

  • 身份验证:使用认证和授权机制来保护API 接口和敏感数据,比如 JWT、OAuth、Session 等。
  • 密码安全:存储用户密码时,使用加密算法和哈希函数进行安全处理,避免直接存储明文密码。
  • 安全头部:在  API 的响应中添加适当的安全头部信息(如 CSRF、CORS、HSTS),以提供更好的安全性。
  • 输入验证:对用户输入的数据进行验证和过滤,以避免潜在的安全漏洞和攻击。
  • 日志和错误处理:及时记录日志和处理错误,以便及时发现和解决潜在的安全问题。

参考