FastAPI操作关系型数据库

FastAPI可以和任何数据库和任意样式的库配合使用,这里看一下使用SQLAlchemy的示例。下面的示例很容易的调整为PostgreSQLMySQLSQLiteOracle等。当前示例中我们使用SQLite

ORM对象关系映射

FastAPI可以与任何数据库在任何样式的库中一起与数据库进行通信。一种常见的模式就是“ORM”:对象关系映射。所谓对象关系映射就是,ORM具有在代码和数据库表(“关系型”)中的对象中间转换(“映射”)的工具。即使用ORM,在SQL数据库创建一个代表映射的类,该类的每个数据代表数据表中的一个列,具有名称和类型。约定俗成:类使用大写如Pet,代表SQL为表的pets,该累的每个实例对象标识数据库中的一行数据。比如一个对象orion_cat(Pet的一个实例)可以有一个属性orion_cat.type, 对标数据库中的type列。并且该属性的值可以是其它,例如"cat"

文件结构

假设有个fastapi_sqlalchemy的项目,其下有一个包为sql_app,结构如下所示:

fastapi_sqlalchemy
├── sql_app
│   ├── __init__.py
│   ├── crud.py
│   ├── database.py
│   ├── main.py
│   ├── models.py
│   ├── requirements.txt
│   └── schemas.py
└── sql_app.db

既然是sql_app包,肯定少不了__init__.py,这里的初始化函数为空。其中依赖requirement.txt中为

fastapi==0.111.0
pydantic==2.7.4
SQLAlchemy==2.0.30

📢📢:这里使用的SQLAlchemy 为2.0以上版本,如果使用v1,则有些语法不同。

创建SQLAlchemy部件

首先看一下sql_app/database.py

创建SQLAlchemy引擎和初始化Base类

# @File : database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"

# 来允许SQLite这样
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={
   "check_same_thread": False}
)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 用于建立数据库SQLAlchemy模型models
Base = declarative_base()


创建一个SQLAlchemy 引擎,其中connect_args={“check_same_thread”: False} 仅用于SQLite,其他数据库不需要 。

默认情况下,SQLite 只允许一个线程与其通信,假设有多个线程的话,也只将处理一个独立的请求。这是为了防止意外地为不同的事物(不同的请求)共享相同的连接。但是在 FastAPI 中,使用普通函数(def)时,多个线程可以为同一个请求与数据库交互,所以我们需要使用connect_args={“check_same_thread”: False}来让SQLite允许这样。

此外,我们将确保每个请求都在依赖项中获得自己的数据库连接会话,因此不需要该默认机制。

连接到一个SQLite数据库,该文件在当前目录下的sql_app.db中

创建SessionLocal的时候,每个 SessionLocal 的类的实例都是一个数据库会话,当然该类本身还不是数据库会话。但是一旦我们创建了一个SessionLocal类的实例,这个实例将是实际的数据库会话。我们将它命名为SessionLocal是为了将它与我们从 SQLAlchemy 导入的Session区别开来。稍后我们将使用Session(从 SQLAlchemy 导入的那个)。要创建SessionLocal类,请使用函数sessionmaker

Base = declarative_base(),在后面的会继承这个Base类,来创建每个数据库模型或者类(ORM模型)

创建数据库模型models

在文件sql_app/models.py中,使用上一步创建的Base类派生子类来创建SQLAlchemy模型。
📢📢:

  1. SQLAlchemy中的“模型”指的的是和数据库交互的类和实例
  2. Pydantic中的“模型”指的是不同的东西,即数据验证、转换以及文档类和实例
# @File : models.py


from sql_app.database import Base

from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)  # primary_key 为True标识主键
    email = Column(String, unique=True, index=True)  # unique 如果为True表示这列不允许出现重复的值,index=True为这列创建索引,提升查询效率
    hashed_password = Column(String)
    is_active = Column(Boolean, default=True)  # default=True 为这列设置默认值

    items = relationship(
### FastAPI 整合关系型数据库的方法 #### 1. 使用同步方式整合关系型数据库 对于传统的同步操作,可以直接使用像 SQLAlchemy 这样的 ORM 工具来管理与数据库的交互。创建一个简单的 SQLite 数据库连接并定义模型: ```python from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker DATABASE_URL = "sqlite:///./test.db" engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True, index=True) name = Column(String, unique=True, index=True) ``` 为了确保每次请求都能获得独立的会话,在 FastAPI 路由处理器中加入如下依赖函数[^2]。 #### 2. 异步方式整合关系型数据库 当追求更高的并发性能时,则推荐采用异步驱动的方式来进行数据库访问。这里以 `fastapi-crud-async` 项目为例说明如何设置基于 PostgreSQL 的异步 CRUD 操作[^3]。 安装必要的 Python 包: ```bash pip install fastapi uvicorn asyncpg databases sqlalchemy[asyncio] ``` 接着修改之前的代码片段使其支持异步特性: ```python import asyncio from typing import AsyncGenerator from fastapi import Depends, FastAPI from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker app = FastAPI() ASYNC_DATABASE_URL = "postgresql+asyncpg://user:password@localhost/dbname" async_engine = create_async_engine( ASYNC_DATABASE_URL, echo=True, ) async_session = sessionmaker( async_engine, class_=AsyncSession, expire_on_commit=False, ) @app.middleware("http") async def db_session_middleware(request, call_next): response = None try: request.state.db = await get_db() response = await call_next(request) finally: await request.state.db.close() return response async def get_db() -> AsyncGenerator: async with async_session() as session: yield session ``` 上述代码实现了中间件模式下的数据库会话管理和释放逻辑,保证了每个 HTTP 请求都有自己的数据库事务上下文[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值