you are already on the right track. you are only missing how you wire the session into FastAPI and how migrations work with async.
- For the Engine + Session you can create them like
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/db"
engine = create_async_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(
bind=engine,
class_=AsyncSession,
expire_on_commit=False,
)
- after that you add the session dependency
from fastapi import Depends
async def get_session() -> AsyncSession:
async with SessionLocal() as session:
yield session
Then in your routes use them for example:
@app.get("/users")
async def list_users(session: AsyncSession = Depends(get_session)):
result = await session.execute(select(User))
return result.scalars().all()
- Alembic migrations usually trips people up. Alembic itself runs synchronously, so just use the normal Postgres URL (
postgresql://...) in alembic.ini. so in your alembic env file u can use
from app.models import Base
target_metadata = Base.metadata
With that in place, when you run:
alembic revision --autogenerate -m "add users table"
Alembic will compare your current database schema against the Base.metadata from your models and generate the migration script.