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

30
tests/conftest.py Normal file
View File

@@ -0,0 +1,30 @@
"""测试基座httpx ASGITransport 进程内测试,不起真实服务。
默认跑 mongodb 后端(需要本地 27017 有 mongo
跑 mysql 后端DB_BACKEND=mysql MYSQL_DSN=... uv run pytest
"""
import os
import pytest_asyncio
from httpx import ASGITransport, AsyncClient
# 测试用独立库,避免污染开发数据
os.environ.setdefault("MONGO_DB", "app_test")
if os.environ.get("DB_BACKEND") == "mysql":
os.environ["MYSQL_DSN"] = os.environ.get(
"MYSQL_DSN", "mysql+aiomysql://root:root@127.0.0.1:3306/app_test?charset=utf8mb4"
)
from src.main import create_app
@pytest_asyncio.fixture
async def client():
app = create_app()
async with AsyncClient(
transport=ASGITransport(app=app), base_url="http://test"
) as ac:
# 手动触发 lifespanASGITransport 不自动跑 lifespan
async with app.router.lifespan_context(app):
yield ac