Files
writer-work-flow/apps/api/ww_api/routers/templates.py
Yaojia Wang cfe6a535b0 feat(templates): F3b 模板库 repo + 端点(GET/POST/DELETE /templates)
- TemplateRepo/SqlTemplateRepo(list/create/delete,owner stub 过滤,只 flush 端点 commit)
- schemas/templates.py(title/body min_length=1→422)+ routers/templates.py(删不存在→404)+ main 注册
- 单测:repo CRUD/owner 隔离/frozen + 端点 201/列出/204/422×2/404
2026-06-23 20:17:32 +02:00

91 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""模板库端点F3 / 契约 §F3
单用户本地版:作者保存/复用提示词模板,可一键填入生成器的 brief/text。
**不做分享/市场**需多租户。owner_id 全程 stub单用户原型
- GET /templates 列出当前用户的模板。
- POST /templates 新建模板201title/body 空 → 422
- DELETE /templates/:id 删除模板204不存在 → 404
提交边界:`TemplateRepo.create`/`delete` 只 `flush()`,端点写后 `await session.commit()`
(仿 rules/foreshadow 写侧,见 memory/gotchas
"""
from __future__ import annotations
import uuid
from typing import Annotated
from fastapi import APIRouter, Depends, Request, Response
from sqlalchemy.ext.asyncio import AsyncSession
from ww_core.domain import TemplateCreate, TemplateRepo
from ww_db import get_session
from ww_shared import AppError, ErrorCode
from ww_api.logging_config import get_logger
from ww_api.schemas.templates import TemplateCreateRequest, TemplateResponse
from ww_api.services.credentials import STUB_OWNER_ID
from ww_api.services.project_deps import get_template_repo
log = get_logger("ww.api.templates")
router = APIRouter(prefix="/templates", tags=["templates"])
TemplateRepoDep = Annotated[TemplateRepo, Depends(get_template_repo)]
SessionDep = Annotated[AsyncSession, Depends(get_session)]
@router.get("")
async def list_templates(repo: TemplateRepoDep) -> list[TemplateResponse]:
"""列出当前用户stub的模板。"""
views = await repo.list_for_owner(STUB_OWNER_ID)
return [
TemplateResponse(
id=v.id, title=v.title, body=v.body, category=v.category, tool_key=v.tool_key
)
for v in views
]
@router.post("", status_code=201)
async def create_template(
body: TemplateCreateRequest,
request: Request,
repo: TemplateRepoDep,
session: SessionDep,
) -> TemplateResponse:
"""新建模板201。title/body 空 → FastAPI 422schema `min_length=1`)。"""
request_id = getattr(request.state, "request_id", None)
view = await repo.create(
STUB_OWNER_ID,
TemplateCreate(
title=body.title, body=body.body, category=body.category, tool_key=body.tool_key
),
)
await session.commit()
log.info("template_created", template_id=str(view.id), request_id=request_id)
return TemplateResponse(
id=view.id,
title=view.title,
body=view.body,
category=view.category,
tool_key=view.tool_key,
)
@router.delete("/{template_id}", status_code=204)
async def delete_template(
template_id: uuid.UUID,
request: Request,
repo: TemplateRepoDep,
session: SessionDep,
) -> Response:
"""删除模板204。不存在 → 404 NOT_FOUND。"""
request_id = getattr(request.state, "request_id", None)
deleted = await repo.delete(STUB_OWNER_ID, template_id)
if not deleted:
raise AppError(ErrorCode.NOT_FOUND, f"template not found: {template_id}")
await session.commit()
log.info("template_deleted", template_id=str(template_id), request_id=request_id)
return Response(status_code=204)