fastapi: 第二十五章:用sqlalchemy访问mysql数据库

一,创建相应的数据库:

image

二,安装sqlalchemy和mysql驱动

$ pip install sqlalchemy aiomysql pydantic

三,代码

database.py

# app/core/database.py
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
# 数据库连接URL
# 格式:数据库类型+驱动://用户名:密码@主机:端口/数据库名
DATABASE_URL = "mysql+aiomysql://root:rootpassword@localhost:3306/media_bank"

# 创建异步引擎
# engine 是数据库连接的核心对象,负责管理连接池
engine = create_async_engine(
    DATABASE_URL,
    echo=True,  # 打印SQL语句,方便调试,生产环境应设为False
    pool_size=10,  # 连接池大小
    max_overflow=20  # 连接池溢出后的最大连接数
)

# 创建会话工厂
# AsyncSessionLocal 可以创建数据库会话对象
AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False)

# 创建模型基类
# 所有的数据模型都要继承这个类
Base = declarative_base()

# 获取数据库会话的依赖函数
async def get_db():
    async with AsyncSessionLocal() as session:
        try:
            yield session  # 把会话交给接口使用
            await session.commit()  # 正常结束则提交事务
        except Exception:
            await session.rollback()  # 发生异常则回滚
            raise
        finally:
            await session.close()  # 关闭会话

model的基类,包含公共字段

from app.core.database import Base
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from datetime import datetime
from sqlalchemy import  func
# 定义一个基类,包含公共字段
class BaseModel(Base):
    __abstract__ = True  # 这个类不会创建表,只是用来继承

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True,comment='主键')
    created_at: Mapped[datetime] = mapped_column(server_default=func.now(),comment="创建时间")
    updated_at: Mapped[datetime] = mapped_column(server_default=func.now(),onupdate=func.now(), comment="最新修改时间")

产品类:

# app/models/products.py
from app.core.basemodel import BaseModel
from sqlalchemy.orm import  Mapped, mapped_column
from sqlalchemy import String

# 商品模型
class Product(BaseModel):
    __tablename__ = "products"

    name: Mapped[str] = mapped_column(String(100),server_default="''", comment='商品名称')
    price: Mapped[int] = mapped_column(comment='价格')
    stock: Mapped[bool] = mapped_column(comment='库存')

路由中访问model类:

# app/api/products.py
from fastapi import APIRouter, Request, Depends

from app.core.database import get_db
from app.core.logger import logger
from app.models.products import Product
from app.utils.log_util import get_query_param
from app.utils.response import success,fail
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select # 2.0 推荐使用 select 语法
import app.models

router = APIRouter(prefix="/products", tags=["商品管理"])

@router.get("/all")
async def get_all_products(request: Request, db: AsyncSession = Depends(get_db)):
    # 异步写法不能直接用 db.query(),必须用 select
    skip = 0
    limit = 10
    stmt = select(Product).offset(skip).limit(limit)
    result = await db.execute(stmt)  # 必须 await 数据库 I/O
    prods = result.scalars().all()
    res = {
        "list": prods,
    }
    return success(data=res)

说明:手动创建数据表,并插入几条测试数据

四,测试效果 :

image

posted @ 2026-06-12 10:53  刘宏缔的架构森林  阅读(16)  评论(0)    收藏  举报