title: FastAPI与SQLAlchemy数据库集成与CRUD操作

date: 2025/04/16 09:50:57

updated: 2025/04/16 09:50:57

author: cmdragon

excerpt:

FastAPI与SQLAlchemy集成基础包括环境准备、数据库连接配置和模型定义。CRUD操作通过数据访问层封装和路由层实现,确保线程安全和事务管理。常见错误如422请求验证错误通过Pydantic模型和中间件处理。Session生命周期管理依赖注入系统保证每个请求独立会话。常见报错如数据库连接失败和事务回滚通过检查服务状态、验证连接参数和异常处理解决。

categories:

  • 后端开发
  • FastAPI

tags:

  • FastAPI
  • SQLAlchemy
  • 数据库集成
  • CRUD操作
  • Session管理
  • 错误处理
  • MySQL


扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意

1. FastAPI 与 SQLAlchemy 同步数据库集成基础

1.1 环境准备与安装

首先创建虚拟环境并安装必要依赖:

python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate.bat # Windows
pip install fastapi uvicorn sqlalchemy pymysql

1.2 数据库连接配置

database.py中配置核心数据库连接:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = "mysql+pymysql://user:password@localhost/mydatabase"
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
pool_size=20,
max_overflow=0,
pool_pre_ping=True
) SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine,
expire_on_commit=False
)

1.3 模型定义与关系映射

models.py中定义数据模型:

from sqlalchemy import Column, Integer, String
from database import Base class User(Base):
__tablename__ = "users" id = Column(Integer, primary_key=True, index=True)
name = Column(String(50), nullable=False)
email = Column(String(100), unique=True)
age = Column(Integer, default=18) def __repr__(self):
return f"<User(name='{self.name}', email='{self.email}')>"

2. CRUD 操作标准实现模式

2.1 数据访问层封装

创建repository.py实现CRUD操作:

from sqlalchemy.orm import Session
from models import User class UserRepository:
@staticmethod
def create_user(db: Session, user_data: dict):
""" 创建用户 """
db_user = User(**user_data)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user @staticmethod
def get_user(db: Session, user_id: int):
""" 根据ID获取用户 """
return db.query(User).filter(User.id == user_id).first() @staticmethod
def update_user(db: Session, user_id: int, update_data: dict):
""" 更新用户信息 """
db_user = db.query(User).filter(User.id == user_id).first()
if db_user:
for key, value in update_data.items():
setattr(db_user, key, value)
db.commit()
db.refresh(db_user)
return db_user @staticmethod
def delete_user(db: Session, user_id: int):
""" 删除用户 """
db_user = db.query(User).filter(User.id == user_id).first()
if db_user:
db.delete(db_user)
db.commit()
return True
return False

2.2 路由层实现

main.py中定义API端点:

from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.orm import Session
from models import Base
from database import engine, SessionLocal
from repository import UserRepository
from pydantic import BaseModel Base.metadata.create_all(bind=engine) app = FastAPI() # 依赖注入获取数据库会话
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close() class UserCreate(BaseModel):
name: str
email: str
age: int = 18 @app.post("/users/")
def create_user(user: UserCreate, db: Session = Depends(get_db)):
return UserRepository.create_user(db, user.dict()) @app.get("/users/{user_id}")
def read_user(user_id: int, db: Session = Depends(get_db)):
db_user = UserRepository.get_user(db, user_id)
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
return db_user

3. Session 生命周期管理

3.1 Session 线程安全策略

通过依赖注入系统保证每个请求独立会话:

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

3.2 事务管理最佳实践

def transfer_funds(db: Session, from_id: int, to_id: int, amount: float):
try:
from_user = UserRepository.get_user(db, from_id)
to_user = UserRepository.get_user(db, to_id) if from_user.balance < amount:
raise ValueError("Insufficient funds") from_user.balance -= amount
to_user.balance += amount db.commit()
except Exception as e:
db.rollback()
raise e

4. 常见错误处理

4.1 422 请求验证错误

示例场景

{
"detail": [
{
"loc": [
"body",
"age"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}

解决方案

  1. 检查请求体是否匹配Pydantic模型定义
  2. 使用OpenAPI文档进行测试
  3. 添加中间件捕获验证错误:
from fastapi.exceptions import RequestValidationError

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
return JSONResponse(
status_code=400,
content={"detail": exc.errors(), "body": exc.body},
)

课后Quiz

问题1:以下哪种方式可以有效防止SQL注入攻击?

A) 使用字符串拼接SQL语句

B) 使用ORM的查询参数化功能

C) 在数据库连接字符串添加特殊参数

D) 禁用所有输入验证

答案:B) 正确。SQLAlchemy等ORM框架会自动进行参数化查询,将用户输入作为参数传递而不是直接拼接到SQL语句中。

问题2:为什么需要在finally块中关闭数据库会话?

A) 为了提升查询性能

B) 确保会话在任何情况下都会被正确关闭

C) 防止其他请求使用该会话

D) 满足数据库连接池的要求

答案:B) 正确。无论是否发生异常,finally块中的代码都会执行,保证会话资源的正确释放。

常见报错解决方案

**报错1

**:sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost'")

原因分析

  • 数据库服务未启动
  • 连接参数(用户名/密码/端口)错误
  • 网络防火墙阻止连接

解决方案

  1. 检查MySQL服务状态
  2. 验证连接字符串参数
  3. 使用telnet测试端口连通性
  4. 添加连接超时参数:
create_engine(connect_args={"connect_timeout": 10})

**报错2

**:sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush.

原因分析

  • 数据库操作违反约束(如唯一性约束)
  • 事务未正确处理异常

解决方案

  1. 检查数据完整性约束
  2. 在事务代码块中添加try/except
  3. 执行显式回滚操作
  4. 使用session.expire_all()重置会话状态

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:FastAPI与SQLAlchemy数据库集成与CRUD操作 | cmdragon's Blog

往期文章归档:

FastAPI与SQLAlchemy数据库集成与CRUD操作的更多相关文章

  1. 【翻译】MongoDB指南/CRUD操作(四)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(四) 1 查询方案(Query Plans) MongoDB 查询优化程序处理查询并且针对给定可利用的索引选 ...

  2. 【翻译】MongoDB指南/CRUD操作(三)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(三) 主要内容: 原子性和事务(Atomicity and Transactions),读隔离.一致性和新近 ...

  3. 【翻译】MongoDB指南/CRUD操作(二)

    [原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(二) 主要内容: 更新文档,删除文档,批量写操作,SQL与MongoDB映射图,读隔离(读关 ...

  4. 【翻译】MongoDB指南/CRUD操作(一)

    [原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(一) 主要内容:CRUD操作简介,插入文档,查询文档. CRUD操作包括创建.读取.更新和删 ...

  5. ASP.NET Core Web API Cassandra CRUD 操作

    在本文中,我们将创建一个简单的 Web API 来实现对一个 “todo” 列表的 CRUD 操作,使用 Apache Cassandra 来存储数据,在这里不会创建 UI ,Web API 的测试将 ...

  6. MongoDB的CRUD操作

    1. 前言 在上一篇文章中,我们介绍了MongoDB.现在,我们来看下如何在MongoDB中进行常规的CRUD操作.毕竟,作为一个存储系统,它的基本功能就是对数据进行增删改查操作. MongoDB中的 ...

  7. 【Java EE 学习 44】【Hibernate学习第一天】【Hibernate对单表的CRUD操作】

    一.Hibernate简介 1.hibernate是对jdbc的二次开发 2.jdbc没有缓存机制,但是hibernate有. 3.hibernate的有点和缺点 (1)优点:有缓存,而且是二级缓存: ...

  8. 使用MyBatis对表执行CRUD操作

    一.使用MyBatis对表执行CRUD操作——基于XML的实现 1.定义sql映射xml文件 userMapper.xml文件的内容如下: <?xml version="1.0&quo ...

  9. MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作(转载)

    本文转载自:http://www.cnblogs.com/jpf-java/p/6013540.html 上一篇博文MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybati ...

  10. MyBatis入门学习教程-使用MyBatis对表执行CRUD操作

    上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...

随机推荐

  1. 拥有自己的解析器(C#实现LALR(1)语法解析器和miniDFA词法分析器的生成器)

    拥有自己的解析器(C#实现LALR(1)语法解析器和miniDFA词法分析器的生成器) 参考lex和yacc的输入格式,参考虎书<现代编译原理-C语言描述>的算法,不依赖第三方库,大力整合 ...

  2. python ModuleNotFoundError_ No module named 'xxx'的解决方案

    本文主要针对的自己写的包无法正常import的情况,如果是第三方包的话正常来说没有问题. 第三方包 主要考虑没有安装对应的版本以及包名写错了等奇葩情况,具体可参考ModuleNotFoundError ...

  3. dart中所有的循环详解

    List MyList = ['苹果', '栗子', '小苹果']; for (var i = 0; i < MyList.length; i++) { print(MyList[i]); } ...

  4. 重试机制与 CompletableFuture 拓展

    重试机制与 CompletableFuture 拓展 禁止转载. 本文旨在讨论重试机制的特点和策略,分析常用重试类库的实现,讨论为 CompletableFuture 添加重试机制的方法.文章首发同名 ...

  5. Layer子域名挖掘机

    Layer子域名挖掘机 Layer子域名挖掘机是一款功能强大的域名查询工具,主要用于提供网站子域名的查询服务. 域名与子域名 域名 域名,又称网域,是互联网上用于标识特定计算机或计算机组的一串由点分隔 ...

  6. 8-2 MySQL 索引的设计原则(超详细说明讲解)

    8-2 MySQL 索引的设计原则(超详细说明讲解) @ 目录 8-2 MySQL 索引的设计原则(超详细说明讲解) 1. 测试数据准备 2. 哪些情况适合创建索引 2.1 字段的数值有唯一性的限制 ...

  7. Hadoop - [04] 分布式部署

    Zookeeper的分布式部署 >> Hadoop的分布式部署 一.集群规划 主机名 node01 node02 node03 JDK ○ ○ ○ Zookeeper ○ ○ ○ Name ...

  8. CF1793E题解

    \(\text{Problem - 1793E - Codeforces}\) \(\text{*2600}\) 备注 2024.10.19 考试 T2.考场未能想出正解,找到性质但没有根据性质往 d ...

  9. 基于 Trae Claude-3.7 从0到1 打造加密货币钱包Dompet-App

    从0到1:用Trae Claude-3.7打造加密货币钱包Dompet-App 项目介绍 大家好!今天我要分享如何使用强大的AI助手Trae Claude-3.7,从零开始构建一款功能丰富的加密货币钱 ...

  10. phpinclude-labs做题记录

    Level 1 file协议 payload:?wrappers=/flag Level 2 data协议 去包含data协议中的内容其实相当于进行了一次远程包含,所以data协议的利用条件需要 ph ...