FastAPI猜字谜实战(5):会话管理

这是系列的第五篇。前四篇,我已经能开局、能聊天了,但玩过的局全散落在 sessions 目录里,玩家根本看不见也挑不了。这一篇我补上读取和删除:把历史列出来、把某一局读回来、把不要的删掉。

一、只有新建是不够的

RESTful 那套规则我在第一篇记过:网址找东西、请求方式定动作 。

新建用了 POST /api/sessions,那读取就用 GET,删除就用 DELETE。

这一篇我要实现三个接口:

  1. 给用户看有哪些局的列表接口。

  2. 点进某一局把内容读回来的详情接口。

  3. 把不要的局删掉的删除接口。

(至于给局改名那个 PUT,我留到最后收官再一起补。)

二、详情接口:把某一局整个读回来

先做最简单的:根据会话 id,把那局的完整 JSON 读出来。这里用路径参数,把 id 直接写进网址:

@app.get("/api/sessions/{session_id}", response_model=ApiResponse, summary="获取指定会话信息", tags="会话管理")

def get_session(session_id: str) -> ApiResponse:

session_file = get_session_file_name(session_id)

with open(session_file, "r", encoding="utf-8") as f:

session_data = json.load(f)

return ApiResponse(code=200, message="获取会话信息成功", data=session_data)

{session_id} 会被 FastAPI 自动接进函数的参数里。我直接复用上一篇那个 get_session_file_name 把 id 变成文件路径,读出来整个塞进 data 返回。前端拿到这个,就能把这局的历史消息全铺出来了。

三、删除接口:先确认存在再删

删除看着一行 os.remove 就行,但我不敢直接删。万一 id 传错了、文件根本没有,os.remove 会直接抛异常。所以我先判断文件是否存在:

@app.delete("/api/sessions/{session_id}", response_model=ApiResponse, summary="删除指定会话", tags="会话管理")

def delete_session(session_id: str) -> ApiResponse:

session_file = get_session_file_name(session_id)

if session_file.exists():

os.remove(session_file)

return ApiResponse(code=200, message="删除会话成功", data=None)

文件在才删,不在也不报错,照样返回成功。 删除这种动作本来也没有数据要回,所以 data 我给 None。

四、列表接口:读目录、排序、返回对象

这个稍微麻烦一点。历史会话全躺在 sessions 目录里,一个 json 文件就是一局。我要做的是把目录里的文件挨个读一遍,提取每局的关键信息,拼成一个列表。

@app.get("/api/sessions", response_model=ApiResponse, summary="获取会话列表", tags="会话管理")

def get_sessions() -> ApiResponse:

file_names = os.listdir(SESSIONS_DIR)

sessions = \[\]

for name in file_names:

if not name.endswith(".json"):

continue

session_id = os.path.splitext(name)0

display_name = session_id

messages_count = 0

with open(SESSIONS_DIR / name, "r", encoding="utf-8") as f:

data = json.load(f)

display_name = data.get("name") or session_id

messages_count = len(data.get("messages", \[\]))

sessions.append({"id": session_id, "name": display_name, "messages_count": messages_count})

按 id(即时间戳)倒序排,最新的局自然排在最前面

sessions.sort(key=lambda s: s"id", reverse=True)

return ApiResponse(code=200, message="获取会话列表成功", data=sessions)

这段逻辑里有几个我在意的点:

  • 提取 id :文件名去掉 .json 后缀就是那局的 id,我用 os.path.splitext 拆出来。

  • 处理名字 :我读文件里的 name 字段,可新建时 name 是空的,所以我用 data.get("name") or session_id 兜底------有名字就用名字,是空就退回显示 id。

  • 统计条数 :每条我都带上 messages_count,就是这局说了多少句话,用户在列表一眼能看出哪局玩得多。

  • 排序 :我用 sort 按 id 倒序。因为 id 本身就是时间戳,按它倒序排,最新的局自然就排到最前面了,我不用另外存时间。

五、列表为什么返回对象而不是光一串 id

我一开始想省事,列表就返回一堆 id 字符串得了。但马上发现不够用:前端要显示历史,光有 id 它既不知道这局叫什么、也不知道这局有没有内容。

所以我把每一项都做成 {id, name, messages_count} 这样的对象。前端拿到就能直接渲染成一行:名字加条数,再挂上"继续"和"删除"按钮,点"继续"时用的还是那个 id。

数据一次给全,前端就不用为了一行历史来回发好几个请求。

六、跑通三件套

我在 /docs 里连着测了一遍:

  1. 先新建几局、聊几句。

  2. 调列表接口,返回的就是按最新排前的对象数组。

  3. 拿其中一个 id 调详情,那局的 messages 完整回来了。

  4. 挑一个调删除,再列一次,那条就没了。

相关推荐
Ai-_Man1 小时前
Microsoft Copilot对话数据怎么导入到另外一个Microsoft Copilot账号里去?AI导出鸭
开发语言·javascript·人工智能·microsoft·chatgpt·ecmascript·copilot
叼烟扛炮1 小时前
Linux 学习笔记(三十一):线程概念、底层分页机制与初体验
linux·运维·服务器·笔记·学习·1024程序员节
垆边人似月.1 小时前
选型与快速跑通(Tesseract / EasyOCR / PaddleOCR)
前端·python
H.莓飛1 小时前
【数据结构】归并与外排序
linux·服务器·c语言·开发语言·数据结构·visual studio
HY小宝F1 小时前
智能摄像头系统 30 天学习计划 Day 09:用 RTSP 把视频送到网络
网络·学习·音视频
技术老孙1 小时前
给 Agent 装上对话框 —— AgentScope-Java 接入 Spring Boot 与 SSE 流式实战
java·开发语言·spring boot
小猪佩奇TONY1 小时前
Linux 内核学习(19) --- linux waitqueue
linux·学习·waitqueue
m4Rk_1 小时前
【论文阅读】Agent记忆机制(111):FEB-30——别再只用问答准确率评估 Agent Memory
论文阅读·人工智能·学习·开源·github
Carl_奕然1 小时前
【智能体】Loop 的四种设计模式之:Verification Loop(2026 最新版)
人工智能·python·设计模式