"""数据库:SQLite(aiosqlite)+ SQLAlchemy async。""" from __future__ import annotations from collections.abc import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase from config import get_settings class Base(DeclarativeBase): pass _engine = None _session_factory: async_sessionmaker[AsyncSession] | None = None def get_engine(): global _engine, _session_factory if _engine is None: settings = get_settings() db_path = f"{settings.data_dir}/app.db" _engine = create_async_engine(f"sqlite+aiosqlite:///{db_path}", echo=False) _session_factory = async_sessionmaker(_engine, expire_on_commit=False) return _engine def get_session_factory() -> async_sessionmaker[AsyncSession]: get_engine() assert _session_factory is not None return _session_factory async def get_db() -> AsyncGenerator[AsyncSession, None]: async with get_session_factory()() as session: yield session async def init_db() -> None: """启动时建表(MVP 不引 Alembic,模型变更删库重建即可)。""" import models # noqa: F401 确保模型注册 engine = get_engine() async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all)