用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/agusmdev/burntop --skill fastapi-database-setup命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
OpenProse is a programming language for AI sessions. An AI session is a Turing-complete computer; OpenProse structures English into unambiguous control flow. More pattern than framework—it ships as a skill with no dependencies. Activate when: running .prose files, mentioning OpenProse, or orchestrating multi-agent workflows from a script. Use this skill if you ever want to kick off more than one subagent at a time, or orchestrate anything interesting between more than one subagent. Write a .prose file and save it in the .claude-plugin/ directory. Then embody the OpenProse VM, as described in prose.md, and execute it.
Configure Alembic for async SQLAlchemy migrations with PostgreSQL
Create FastAPI application factory with lifespan, middleware, pagination, and router configuration
正在显示 SKILL.md
基于 SOC 职业分类
| name | fastapi-database-setup |
| description | Configure async SQLAlchemy 2.0 engine, session factory, and database dependency for FastAPI |
This skill covers setting up async SQLAlchemy 2.0 with PostgreSQL using asyncpg driver.
Create src/app/database.py:
from collections.abc import AsyncGenerator
from sqlalchemy.ext.asyncio import (
AsyncSession,
async_sessionmaker,
create_async_engine,
)
from app.config import settings
# Create async engine
engine = create_async_engine(
str(settings.database_url),
echo=settings.database_echo,
pool_size=settings.database_pool_size,
max_overflow=settings.database_max_overflow,
pool_pre_ping=True, # Verify connections before use
)
# Create async session factory
async_session_factory = async_sessionmaker(
bind=engine,
class_=AsyncSession,
expire_on_commit=False, # Don't expire objects after commit
autocommit=False,
autoflush=False,
)
async def get_db() -> AsyncGenerator[AsyncSession, None]:
"""
Dependency that provides a database session.
Yields an async session and ensures it's closed after use.
Uses the same session throughout the request lifecycle.
"""
async with async_session_factory() as session:
try:
yield session
finally:
await session.close()
Create src/app/dependencies.py:
from collections.abc import AsyncGenerator
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import async_session_factory
async def get_db() -> AsyncGenerator[AsyncSession, None]:
"""
Dependency that provides a database session.
Usage in routers:
@router.get("/items")
async def list_items(db: AsyncSession = Depends(get_db)):
...
"""
async with async_session_factory() as session:
try:
yield session
finally:
await session.close()
| Option | Purpose | Default |
|---|---|---|
echo | Log all SQL statements | False |
pool_size | Number of persistent connections | 5 |
max_overflow | Additional connections allowed | 10 |
pool_pre_ping | Test connection validity | True |
pool_recycle | Recycle connections after N seconds | -1 (disabled) |
| Option | Purpose | Recommended |
|---|---|---|
expire_on_commit | Expire objects after commit | False |
autocommit | Auto-commit transactions | False |
autoflush | Auto-flush before queries | False |
In async contexts, accessing expired attributes triggers lazy loading, which fails outside an active session. Setting expire_on_commit=False allows accessing model attributes after commit without additional queries.
# With expire_on_commit=True (default) - FAILS
async with session.begin():
item = Item(name="test")
session.add(item)
# item.name would fail here - object expired
# With expire_on_commit=False - WORKS
async with session.begin():
item = Item(name="test")
session.add(item)
# item.name works - object not expired
Manual control over when changes are flushed to the database:
PostgreSQL async connection string format:
postgresql+asyncpg://user:password@host:port/database
Examples:
# Local development
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/myapp
# With SSL
DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/db?ssl=require
# Connection pooler (e.g., PgBouncer)
DATABASE_URL=postgresql+asyncpg://user:pass@pgbouncer:6432/db?prepared_statement_cache_size=0
For tests, use a separate test database:
# In config.py, add:
test_database_url: PostgresDsn | None = None
# In .env.example, add:
TEST_DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/dbname_test
from sqlalchemy import text
async def check_database_health(session: AsyncSession) -> bool:
"""Check if database is accessible."""
try:
await session.execute(text("SELECT 1"))
return True
except Exception:
return False
In your app factory, dispose the engine on shutdown:
@asynccontextmanager
async def lifespan(app: FastAPI):
yield
await engine.dispose()