feat: 改造为开箱即用模板 — MySQL/MongoDB(Beanie) 一键切换 + AGENTS.md 开发规范

- src/ 按域组织骨架,示例域 items 双后端实现(SQLAlchemy2.0 async / Beanie 2.x)
- DB_BACKEND 环境变量切换,router 只依赖 Repo Protocol
- alembic 迁移(含初始 items 迁移)、uv 依赖管理、ruff、pytest 异步测试
- Dockerfile + docker-compose(app/mysql/mongo)
- AGENTS.md 重写为本模板开发规范;原最佳实践文档归档 docs/
- 验证:mongodb/mysql 双后端 pytest 全绿 + uvicorn 真实冒烟通过
This commit is contained in:
2026-08-21 21:23:26 +08:00
parent 5e00aa6095
commit 981bee5a46
34 changed files with 3579 additions and 1256 deletions

33
tests/test_items.py Normal file
View File

@@ -0,0 +1,33 @@
async def test_health(client):
resp = await client.get("/health")
assert resp.status_code == 200
assert resp.json()["status"] == "ok"
async def test_items_crud(client):
# create
resp = await client.post("/api/v1/items", json={"name": "demo", "description": "d"})
assert resp.status_code == 201
item = resp.json()
assert item["name"] == "demo"
item_id = item["id"]
# get
resp = await client.get(f"/api/v1/items/{item_id}")
assert resp.status_code == 200
# list
resp = await client.get("/api/v1/items")
assert resp.status_code == 200
assert resp.json()["total"] >= 1
# update
resp = await client.patch(f"/api/v1/items/{item_id}", json={"name": "demo2"})
assert resp.status_code == 200
assert resp.json()["name"] == "demo2"
# delete
resp = await client.delete(f"/api/v1/items/{item_id}")
assert resp.status_code == 204
resp = await client.get(f"/api/v1/items/{item_id}")
assert resp.status_code == 404