一.整体架构概述
这个代码是一个典型的 FastAPI 管理系统 API 实现,主要包含两部分:
-
API 路由定义部分(api/v1/apis)
-
控制器逻辑部分(controllers/api.py)
这种分层设计是软件开发中常见的模式,它把路由定义和业务逻辑分开,使代码更清晰、更易维护。
二.核心概念讲解
1. FastAPI 基础
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,基于 Python 类型提示。它的优势包括:
-
自动文档生成功能(Swagger UI)
-
数据验证和序列化
-
异步支持
-
简洁的语法
2. 路由与端点
在 FastAPI 中,路由定义在 APIRouter 对象中。每个路由对应一个 HTTP 方法和路径,以及相应的处理函数。
例如:
@router.get("/list", summary="查看API列表")
async def list_api(...):
...
这定义了一个 GET 请求的 "/list" 路径,用于获取 API 列表。
3. 数据模型与 Pydantic
代码中使用了 Pydantic 模型(如 ApiCreate、ApiUpdate)进行数据验证和序列化。这些模型定义了 API 请求和响应的数据结构。
4. Tortoise ORM
Tortoise 是一个异步 ORM(对象关系映射),用于与数据库交互。它使数据库操作更加直观和安全。
三.代码详细讲解
(一)API 路由定义部分(api/v1/apis)
1. 导入模块
from fastapi import APIRouter, Query
from tortoise.expressions import Q
from app.controllers.api import api_controller
from app.schemas import Success, SuccessExtra
from app.schemas.apis import *
这里导入了必要的模块:
-
APIRouter
用于定义 API 路由 -
Query
用于定义查询参数 -
Q
用于构建查询条件 -
api_controller
是业务逻辑控制器 -
Success
和SuccessExtra
是响应模型
2. 定义路由
router = APIRouter()
创建了一个 APIRouter 实例,用于注册 API 路由。
3. 查看 API 列表
@router.get("/list", summary="查看API列表")
async def list_api(
page: int = Query(1, description="页码"),
page_size: int = Query(10, description="每页数量"),
path: str = Query(None, description="API路径"),
summary: str = Query(None, description="API简介"),
tags: str = Query(None, description="API模块"),
):
q = Q()
if path:
q &= Q(path__contains=path)
if summary:
q &= Q(summary__contains=summary)
if tags:
q &= Q(tags__contains=tags)
total, api_objs = await api_controller.list(page=page, page_size=page_size, search=q, order=["tags", "id"])
data = [await obj.to_dict() for obj in api_objs]
return SuccessExtra(data=data, total=total, page=page, page_size=page_size)
-
定义了一个 GET 请求的 "/list" 路径
-
使用
Query
定义了查询参数,包括分页参数和搜索条件 -
构建查询条件
q
,使用Q
对象组合多个条件 -
调用
api_controller.list()
获取分页数据 -
将模型对象转换为字典列表
-
返回
SuccessExtra
响应,包含数据和分页信息
4. 查看单个 API
@router.get("/get", summary="查看Api")
async def get_api(
id: int = Query(..., description="Api"),
):
api_obj = await api_controller.get(id=id)
data = await api_obj.to_dict()
return Success(data=data)
-
定义了一个 GET 请求的 "/get" 路径
-
使用
Query
定义了必需的id
参数 -
调用
api_controller.get()
获取单个 API 对象 -
转换为字典并返回
5. 创建 API
@router.post("/create", summary="创建Api")
async def create_api(
api_in: ApiCreate,
):
await api_controller.create(obj_in=api_in)
return Success(msg="Created Successfully")
-
定义了一个 POST 请求的 "/create" 路径
-
使用
ApiCreate
模型验证请求数据 -
调用
api_controller.create()
创建新 API -
返回成功响应
6. 更新 API
@router.post("/update", summary="更新Api")
async def update_api(
api_in: ApiUpdate,
):
await api_controller.update(id=api_in.id, obj_in=api_in)
return Success(msg="Update Successfully")
-
定义了一个 POST 请求的 "/update" 路径
-
使用
ApiUpdate
模型验证请求数据 -
调用
api_controller.update()
更新 API -
返回成功响应
7. 删除 API
@router.delete("/delete", summary="删除Api")
async def delete_api(
api_id: int = Query(..., description="ApiID"),
):
await api_controller.remove(id=api_id)
return Success(msg="Deleted Success")
-
定义了一个 DELETE 请求的 "/delete" 路径
-
使用
Query
定义了必需的api_id
参数 -
调用
api_controller.remove()
删除 API -
返回成功响应
8. 刷新 API 列表
@router.post("/refresh", summary="刷新API列表")
async def refresh_api():
await api_controller.refresh_api()
return Success(msg="OK")
-
定义了一个 POST 请求的 "/refresh" 路径
-
调用
api_controller.refresh_api()
刷新 API 列表 -
返回成功响应
(二)控制器逻辑部分(controllers/api.py)
1. 导入模块
from fastapi.routing import APIRoute
from app.core.crud import CRUDBase
from app.log import logger
from app.models.admin import Api
from app.schemas.apis import ApiCreate, ApiUpdate
导入了必要的模块:
-
APIRoute
用于判断路由类型 -
CRUDBase
是基础的 CRUD 操作类 -
logger
用于日志记录 -
Api
是数据库模型 -
ApiCreate
和ApiUpdate
是 Pydantic 模型
2. 定义 ApiController 类
class ApiController(CRUDBase[Api, ApiCreate, ApiUpdate]):
def __init__(self):
super().__init__(model=Api)
-
继承了
CRUDBase
类,泛型参数分别为模型类、创建模型和更新模型 -
在构造函数中初始化父类,传入模型类
Api
3. 刷新 API 列表方法
async def refresh_api(self):
from app import app
# 删除废弃API数据
all_api_list = []
for route in app.routes:
# 只更新有鉴权的API
if isinstance(route, APIRoute) and len(route.dependencies) > 0:
all_api_list.append((list(route.methods)[0], route.path_format))
delete_api = []
for api in await Api.all():
if (api.method, api.path) not in all_api_list:
delete_api.append((api.method, api.path))
for item in delete_api:
method, path = item
logger.debug(f"API Deleted {method} {path}")
await Api.filter(method=method, path=path).delete()
for route in app.routes:
if isinstance(route, APIRoute) and len(route.dependencies) > 0:
method = list(route.methods)[0]
path = route.path_format
summary = route.summary
tags = list(route.tags)[0]
api_obj = await Api.filter(method=method, path=path).first()
if api_obj:
await api_obj.update_from_dict(dict(method=method, path=path, summary=summary, tags=tags)).save()
else:
logger.debug(f"API Created {method} {path}")
await Api.create(**dict(method=method, path=path, summary=summary, tags=tags))
-
遍历应用中的所有路由,收集有鉴权的 API 路由信息
-
查找数据库中已不存在的 API 并删除
-
更新现有 API 信息或创建新的 API 记录
4. 创建控制器实例
api_controller = ApiController()
创建了一个 ApiController
实例,供路由部分调用。
四.实用开发技巧
1. 分层架构
将代码分为路由定义和业务逻辑两层,使代码结构更清晰,便于维护和扩展。
2. 使用 Pydantic 验证
利用 Pydantic 模型进行数据验证和序列化,确保数据的正确性和一致性。
3. 异步操作
使用异步数据库操作(如 await api_controller.list()
),提高应用性能。
4. 日志记录
在关键操作处记录日志(如 logger.debug(f"API Created {method} {path}")
),便于问题排查和监控。
5. 自动文档
FastAPI 自动生成 API 文档(Swagger UI),方便测试和查看 API 说明。