102 lines
3.8 KiB
Python
102 lines
3.8 KiB
Python
"""
|
||
业务逻辑层 —— 使用内存假数据实现 Todo 的 CRUD 操作。
|
||
|
||
所有数据存储在内存字典中,服务重启后数据会丢失。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Optional
|
||
from pydantic import BaseModel, Field
|
||
|
||
|
||
# ──────────────────────────────────────────────
|
||
# Pydantic 模型(请求 / 响应)
|
||
# ──────────────────────────────────────────────
|
||
|
||
|
||
class TodoCreate(BaseModel):
|
||
"""创建待办事项的请求体。"""
|
||
title: str = Field(..., min_length=1, max_length=200, description="待办事项标题")
|
||
completed: bool = Field(False, description="是否已完成")
|
||
|
||
|
||
class TodoUpdate(BaseModel):
|
||
"""更新待办事项的请求体(部分更新)。"""
|
||
title: Optional[str] = Field(None, min_length=1, max_length=200, description="待办事项标题")
|
||
completed: Optional[bool] = Field(None, description="是否已完成")
|
||
|
||
|
||
class TodoResponse(BaseModel):
|
||
"""待办事项的响应体。"""
|
||
id: int = Field(..., description="待办事项 ID")
|
||
title: str = Field(..., description="待办事项标题")
|
||
completed: bool = Field(..., description="是否已完成")
|
||
|
||
model_config = {"from_attributes": True}
|
||
|
||
|
||
# ──────────────────────────────────────────────
|
||
# 内存假数据存储
|
||
# ──────────────────────────────────────────────
|
||
|
||
|
||
class TodoService:
|
||
"""待办事项服务 —— 使用内存字典存储数据。"""
|
||
|
||
def __init__(self) -> None:
|
||
self._todos: dict[int, dict] = {}
|
||
self._next_id: int = 1
|
||
self._init_mock_data()
|
||
|
||
def _init_mock_data(self) -> None:
|
||
"""初始化一批假数据,方便演示。"""
|
||
mock_todos = [
|
||
{"title": "学习 FastAPI", "completed": False},
|
||
{"title": "编写单元测试", "completed": False},
|
||
{"title": "阅读 Python 文档", "completed": True},
|
||
{"title": "完成项目报告", "completed": False},
|
||
{"title": "锻炼身体 30 分钟", "completed": True},
|
||
]
|
||
for item in mock_todos:
|
||
self.create_todo(TodoCreate(**item))
|
||
|
||
def list_todos(self) -> list[TodoResponse]:
|
||
"""返回所有待办事项。"""
|
||
return [TodoResponse(**todo) for todo in self._todos.values()]
|
||
|
||
def get_todo(self, todo_id: int) -> Optional[TodoResponse]:
|
||
"""根据 ID 获取单个待办事项,不存在则返回 None。"""
|
||
todo = self._todos.get(todo_id)
|
||
if todo is None:
|
||
return None
|
||
return TodoResponse(**todo)
|
||
|
||
def create_todo(self, todo_in: TodoCreate) -> TodoResponse:
|
||
"""创建新的待办事项并返回。"""
|
||
todo_id = self._next_id
|
||
self._next_id += 1
|
||
todo = {
|
||
"id": todo_id,
|
||
"title": todo_in.title,
|
||
"completed": todo_in.completed,
|
||
}
|
||
self._todos[todo_id] = todo
|
||
return TodoResponse(**todo)
|
||
|
||
def update_todo(self, todo_id: int, todo_in: TodoUpdate) -> Optional[TodoResponse]:
|
||
"""部分更新指定待办事项,不存在则返回 None。"""
|
||
todo = self._todos.get(todo_id)
|
||
if todo is None:
|
||
return None
|
||
update_data = todo_in.model_dump(exclude_unset=True)
|
||
todo.update(update_data)
|
||
return TodoResponse(**todo)
|
||
|
||
def delete_todo(self, todo_id: int) -> bool:
|
||
"""删除指定待办事项,成功返回 True,不存在返回 False。"""
|
||
if todo_id not in self._todos:
|
||
return False
|
||
del self._todos[todo_id]
|
||
return True
|