FastAPI-Soy-Admin开发脚手架中API文档分析

导入模块
from fastapi import APIRouter, Query
from fastapi.params import Depends
from tortoise.expressions import Q

from app.api.v1.utils import refresh_api_list, insert_log, generate_tags_recursive_list
from app.controllers import user_controller
from app.controllers.api import api_controller
from app.core.ctx import CTX_USER_ID
from app.models.system import Api, Role
from app.models.system import LogType, LogDetailType
from app.schemas.apis import ApiCreate, ApiUpdate, ApiSearch
from app.schemas.base import Success, SuccessExtra

导入了FastAPI、Tortoise ORM等必要的模块和自定义的工具函数、控制器、模型、模式等。

创建APIRouter实例
router = APIRouter()

创建了一个APIRouter实例,用于定义API路由。

定义API路由
  1. 查看API列表

@router.post("/apis/all/", summary="查看API列表")
async def _(obj_in: ApiSearch):
    # 构建查询条件
    q = Q()
    if obj_in.api_path:
        q &= Q(api_path__contains=obj_in.api_path)
    if obj_in.summary:
        q &= Q(summary=obj_in.summary)
    if obj_in.tags:
        for tag in obj_in.tags:
            q &= Q(tags__contains=[tag])
    if obj_in.status_type:
        q &= Q(status_type=obj_in.status_type)

    # 获取当前用户及其角色
    user_id = CTX_USER_ID.get()
    user_obj = await user_controller.get(id=user_id)
    await user_obj.fetch_related("by_user_roles")
    user_role_objs: list[Role] = await user_obj.by_user_roles
    user_role_codes = [role_obj.role_code for role_obj in user_role_objs]

    # 根据用户角色获取API列表
    if "R_SUPER" in user_role_codes:
        total, api_objs = await api_controller.list(page=obj_in.current, page_size=obj_in.size, search=q, order=["tags", "id"])
    else:
        api_objs: list[Api] = []
        for role_obj in user_role_objs:
            await role_obj.fetch_related("by_role_apis")
            api_objs.extend([api_obj for api_obj in await role_obj.by_role_apis.filter(q)])

        unique_apis = list(set(api_objs))
        sorted_menus = sorted(unique_apis, key=lambda x: x.id)
        # 实现分页
        start = (obj_in.current - 1) * obj_in.size
        end = start + obj_in.size
        api_objs = sorted_menus[start:end]
        total = len(sorted_menus)

    # 转换API对象为字典并返回
    records = []
    for obj in api_objs:
        data = await obj.to_dict(exclude_fields=["create_time", "update_time"])
        records.append(data)
    data = {"records": records}
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiGetList, by_user_id=user_obj.id)
    return SuccessExtra(data=data, total=total, current=obj_in.current, size=obj_in.size)
  • 接收一个ApiSearch对象作为输入,用于指定查询条件。

  • 根据输入条件构建查询条件q

  • 获取当前用户及其角色,根据用户角色获取API列表。超级用户可以直接获取所有符合条件的API,普通用户只能获取其角色关联的API。

  • 对API对象进行分页处理,并转换为字典格式返回。

  • 记录用户操作日志。

  1. 查看单个API

@router.get("/apis/{api_id}", summary="查看API")
async def _(api_id: int):
    api_obj = await api_controller.get(id=api_id)
    data = await api_obj.to_dict(exclude_fields=["id", "create_time", "update_time"])
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiGetOne, by_user_id=0)
    return Success(data=data)
  • 根据API ID获取对应的API对象,并转换为字典格式返回。

  • 记录用户操作日志。

  1. 构建API树

def build_api_tree(apis: list[Api]):
    parent_map = {"root": {"id": "root", "children": []}}
    # 遍历输入数据
    for api in apis:
        tags = api.tags
        parent_id = "root"
        for tag in tags:
            node_id = f"parent${tag}"
            # 如果当前节点不存在,则创建一个新的节点
            if node_id not in parent_map:
                node = {"id": node_id, "summary": tag, "children": []}
                parent_map[node_id] = node
                parent_map[parent_id]["children"].append(node)
            parent_id = node_id
        parent_map[parent_id]["children"].append({
            "id": api.id,
            "summary": api.summary,
        })
    return parent_map["root"]["children"]


@router.get("/apis/tree/", summary="查看API树")
async def _():
    api_objs = await Api.all()
    data = []
    if api_objs:
        data = build_api_tree(api_objs)
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiGetTree, by_user_id=0)
    return Success(data=data)
  • build_api_tree函数:根据API对象的标签构建树形结构。

  • 获取所有API对象,并调用build_api_tree函数构建树形结构返回。

  • 记录用户操作日志。

  1. 创建API

@router.post("/apis", summary="创建API")
async def _(api_in: ApiCreate):
    if isinstance(api_in.tags, str):
        api_in.tags = api_in.tags.split("|")
    new_api = await api_controller.create(obj_in=api_in)
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiCreateOne, by_user_id=0)
    return Success(msg="Created Successfully", data={"created_id": new_api.id})
  • 接收一个ApiCreate对象作为输入,创建新的API对象。

  • 如果标签是字符串格式,则将其分割为列表。

  • 记录用户操作日志。

  1. 更新API

@router.patch("/apis/{api_id}", summary="更新API")
async def _(api_id: int, api_in: ApiUpdate):
    if isinstance(api_in.tags, str):
        api_in.tags = api_in.tags.split("|")
    await api_controller.update(id=api_id, obj_in=api_in)
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiUpdateOne, by_user_id=0)
    return Success(msg="Update Successfully", data={"updated_id": api_id})
  • 根据API ID更新对应的API对象。

  • 如果标签是字符串格式,则将其分割为列表。

  • 记录用户操作日志。

  1. 删除API

@router.delete("/apis/{api_id}", summary="删除API")
async def _(api_id: int):
    await api_controller.remove(id=api_id)
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiDeleteOne, by_user_id=0)
    return Success(msg="Deleted Successfully", data={"deleted_id": api_id})
  • 根据API ID删除对应的API对象。

  • 记录用户操作日志。

  1. 批量删除API

@router.delete("/apis", summary="批量删除API")
async def _(ids: str = Query(..., description="API ID列表, 用逗号隔开")):
    api_ids = ids.split(",")
    deleted_ids = []
    for api_id in api_ids:
        api_obj = await Api.get(id=int(api_id))
        await api_obj.delete()
        deleted_ids.append(int(api_id))
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiBatchDelete, by_user_id=0)
    return Success(msg="Deleted Successfully", data={"deleted_ids": deleted_ids})
  • 接收一个包含API ID列表的字符串,批量删除对应的API对象。

  • 记录用户操作日志。

  1. 刷新API列表

@router.post("/apis/refresh/", summary="刷新API列表")
async def _():
    await refresh_api_list()
    await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiRefresh, by_user_id=0)
    return Success()
  • 调用refresh_api_list函数刷新API列表。

  • 记录用户操作日志。

  1. 查看API tags

@router.post("/apis/tags/all/", summary="查看API tags")
async def _():
    data = await generate_tags_recursive_list()
    # await insert_log(log_type=LogType.UserLog, log_detail_type=LogDetailType.ApiRefresh, by_user_id=0)
    return Success(data=data)
  • 调用generate_tags_recursive_list函数生成递归的标签列表并返回。

  • 注释掉了日志记录代码。

功能逻辑分析

API管理功能
  • 查看API列表:支持根据路径、摘要、标签、状态等条件筛选API,并根据用户角色返回相应的API列表。超级用户可以查看所有API,普通用户只能查看其角色关联的API。

  • 查看单个API:根据API ID获取对应的API详细信息。

  • 构建API树:根据API的标签构建树形结构,方便用户查看和管理API。

  • 创建API:允许用户创建新的API,支持指定API的路径、摘要、标签、状态等信息。

  • 更新API:支持对现有API的信息进行更新,如路径、摘要、标签、状态等。

  • 删除API:可以删除单个API或批量删除多个API。

  • 刷新API列表:提供刷新API列表的功能,可能用于更新缓存或重新加载API配置。

权限控制
  • 根据用户角色(超级用户或普通用户)控制用户可以访问的API列表。超级用户可以访问所有API,普通用户只能访问其角色关联的API。

日志记录
  • 每个API操作(查看列表、查看单个、创建、更新、删除、刷新等)都会记录相应的用户操作日志,方便后续审计和追踪。

数据处理
  • 使用Tortoise ORM进行数据查询和操作,支持复杂的查询条件和分页处理。

  • 在返回API数据时,会排除一些字段(如创建时间和更新时间),以简化响应数据。

树形结构构建
  • 通过build_api_tree函数根据API的标签构建树形结构,便于用户以层次化的方式查看和管理API。

总结

这段代码实现了一个完整的API管理模块,支持对API的增删改查操作,并提供了API树形结构查看、批量操作、权限控制和日志记录等功能。代码结构清晰,功能完善,适合在需要对API进行集中管理和操作的场景中使用。

你可能感兴趣的:(开发脚手架,windows,python,网络)