从 0 到 1 的 ORM 指南:Python+SQLAlchemy+MySQL

作为 Python 生态中最强大的 ORM 框架,SQLAlchemy 几乎是中大型 Python 项目的 “标配”—— 它能帮你用 Python 类操作 MySQL 数据库,彻底告别原生 SQL 的繁琐。

本文针对0 基础小白,从环境搭建→核心概念→CRUD 实战→关系映射,一步步讲清如何用 SQLAlchemy 连接 MySQL。全程代码可复制,每一行都有解释,目标是让你 “学完就能用”。

一、前置准备:环境搭好再开始

在写代码前,必须先搞定 3 件事:安装 MySQL、安装 Python 库、配置连接。

1. 安装 MySQL(新手推荐用 Docker,避免踩坑)

如果不想折腾 MySQL 的安装(比如 Windows 下的环境变量、权限问题),直接用 Docker 跑 MySQL——1 条命令就能启动:

# 启动MySQL 8.0容器(密码设为root123,端口映射3306) docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0 

验证是否启动成功:

docker ps # 看mysql容器是否在运行 

2. 安装 Python 依赖库

需要两个库:

  • pymysql:Python 连接 MySQL 的驱动;
  • sqlalchemy:核心 ORM 框架。

用 pip 安装:

pip install pymysql sqlalchemy 

3. 测试 MySQL 连接(避免后续踩坑)

先写一段代码,验证能否连接到 MySQL:

from sqlalchemy import create_engine # MySQL连接字符串格式:mysql+pymysql://用户名:密码@主机:端口/数据库名 # 注意:首次连接需要先在MySQL中创建数据库(比如test_db) engine = create_engine('mysql+pymysql://root:root123@localhost:3306/test_db') # 测试连接(无报错则成功) with engine.connect() as conn: print("连接成功!") 

关键说明

  • 连接字符串中的test_db需要先在 MySQL 中创建(用 Navicat 或命令行CREATE DATABASE test_db;);
  • 如果用本地 MySQL 而非 Docker,hostlocalhost,密码填你安装时设置的密码。

二、SQLAlchemy 核心概念:3 个组件搞定 ORM

SQLAlchemy 的核心是 **“用对象封装数据库操作”**,你需要先理解 3 个关键组件:

1. Engine:数据库连接的 “总开关”

  • 作用:管理数据库连接池(不用每次操作都新建连接,提升性能);
  • 类比:像家里的 “总电源开关”,控制所有电器的供电。

创建 Engine 的代码:

from sqlalchemy import create_engine # 连接字符串格式:mysql+pymysql://用户名:密码@主机:端口/数据库名 engine = create_engine( 'mysql+pymysql://root:root123@localhost:3306/test_db', echo=True, # 打印执行的SQL(调试用,上线关闭) pool_size=5, # 连接池大小(默认5) max_overflow=10 # 超出连接池后的最大连接数(默认10) ) 

2. Base:所有模型的 “模板”

  • 作用:定义模型类的基类,自动映射类到数据库表;
  • 类比:像 “建筑图纸”,所有房子(模型类)都基于这个图纸建造。

创建 Base 的代码:

from sqlalchemy.orm import declarative_base # 创建模型基类(所有模型类都要继承它) Base = declarative_base() 

3. Session:操作数据库的 “把手”

  • 作用:负责和数据库交互(新增、查询、更新、删除);
  • 类比:像 “遥控器”,通过它控制电视(数据库)的操作。

创建 Session 的代码:

from sqlalchemy.orm import sessionmaker # 创建Session工厂(绑定Engine) SessionLocal = sessionmaker(bind=engine) # 获取Session实例(每次操作都要新建Session) session = SessionLocal() 

总结:Engine→连接池→Session→操作数据库;Base→模型类→表结构。

三、实战 1:定义第一个模型类 ——User 表

现在,我们用 Base 定义一个User类,对应 MySQL 的users表。

1. 定义模型类

from sqlalchemy import Column, Integer, String, DateTime from sqlalchemy.sql import func from datetime import datetime # 继承Base基类 class User(Base): __tablename__ = 'users' # 对应数据库的users表(必须小写) # 字段定义(Column是表字段的装饰器) id = Column(Integer, primary_key=True, index=True) # 主键(自增) name = Column(String(50), nullable=False) # 姓名(非空) email = Column(String(100), unique=True, index=True) # 邮箱(唯一,加索引) age = Column(Integer) # 年龄(可选) created_at = Column(DateTime(timezone=True), default=func.now()) # 创建时间(自动填充当前时间) 

关键说明

  • __tablename__:模型类对应的表名(必须和数据库中的表名一致,MySQL 默认小写);
  • primary_key=True:标记为主键(自增);
  • nullable=False:字段非空(插入数据时必须传值);
  • unique=True:字段唯一(避免重复邮箱);
  • func.now():用 MySQL 的NOW()函数自动填充当前时间(比 Python 的datetime.now()更准确)。

2. 创建表结构(让模型映射到数据库)

定义好模型类后,需要用 Base 创建表:

# 创建所有继承Base的模型对应的表(第一次运行时执行) Base.metadata.create_all(bind=engine) 

注意

  • 这段代码只会创建不存在的表(不会覆盖已有表);
  • 如果修改了模型类(比如新增字段),需要用迁移工具(如 Alembic)更新表结构(本文暂不展开)。

四、实战 2:CRUD 操作 —— 像 “操作 Python 对象” 一样操作数据库

现在,我们用 Session 实现增删改查,全程不用写 SQL!

1. 新增数据(Create)

# 创建User实例(相当于数据库中的一行数据) user = User(name='张三', email='[email protected]', age=18) # 将实例添加到Session(相当于“暂存”) session.add(user) # 提交Session(相当于“确认”,将数据写入数据库) session.commit() # 刷新实例(获取自增的id) session.refresh(user) print(f"新增用户ID:{user.id}") 

关键说明

  • add()只是将数据 “暂存” 到 Session,必须 commit () 才会写入数据库
  • refresh()会从数据库中获取最新数据(比如自增的 id)。

2. 查询数据(Read)

SQLAlchemy 提供了强大的查询 API,常用的有:

(1)根据主键查询(最常用)
# 根据id=1查询用户 user = session.get(User, 1) if user: print(f"用户姓名:{user.name},邮箱:{user.email}") else: print("用户不存在") 
(2)条件查询(比如查年龄≥18 的用户)
from sqlalchemy import select # 构建查询语句(SELECT * FROM users WHERE age >= 18) stmt = select(User).where(User.age >= 18) # 执行查询(返回所有符合条件的用户) users = session.execute(stmt).scalars().all() for user in users: print(f"ID:{user.id},姓名:{user.name}") 
(3)模糊查询(比如查姓名包含 “张” 的用户)
stmt = select(User).where(User.name.like('%张%')) users = session.execute(stmt).scalars().all() 

3. 更新数据(Update)

# 先查询要修改的用户 user = session.get(User, 1) # 修改属性 user.age = 20 user.email = '[email protected]' # 提交修改(自动生成UPDATE语句) session.commit() 

4. 删除数据(Delete)

# 先查询要删除的用户 user = session.get(User, 1) # 删除实例 session.delete(user) # 提交删除(自动生成DELETE语句) session.commit() 

五、实战 3:关系映射 —— 处理表之间的 “一对多” 关系

实际项目中,表之间一定有关系(比如用户和订单的 “一对多”),SQLAlchemy 能自动处理这些关系。

1. 定义关联模型(比如 Order 表)

class Order(Base): __tablename__ = 'orders' id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey('users.id')) # 外键(关联users表的id) product = Column(String(100), nullable=False) price = Column(Integer, nullable=False) created_at = Column(DateTime(timezone=True), default=func.now()) # 关系映射:Order→User(多对一) user = relationship('User', back_populates='orders') # back_populates指向User的orders属性 

2. 在 User 表中添加反向关系

class User(Base): __tablename__ = 'users' # 之前的字段... # 反向关系:User→Order(一对多) orders = relationship('Order', back_populates='user') # back_populates指向Order的user属性 

3. 测试关系映射

# 创建用户 user = User(name='李四', email='[email protected]', age=25) session.add(user) session.commit() # 创建订单(自动关联user_id) order1 = Order(user_id=user.id, product='手机', price=5999) order2 = Order(user_id=user.id, product='电脑', price=9999) session.add_all([order1, order2]) session.commit() # 查询用户的所有订单(通过user.orders) user = session.get(User, user.id) for order in user.orders: print(f"订单ID:{order.id},商品:{order.product},价格:{order.price}") 

关键说明

  • ForeignKey('users.id'):Order 表的user_id关联 User 表的id(外键约束);
  • relationship:定义模型之间的关系(比如 User 的orders属性会自动查询该用户的所有订单);
  • back_populates:双向关联(User 的orders和 Order 的user互相引用)。

六、进阶:优化与避坑 —— 小白必看!

1. 连接池配置(提升性能)

Engine 默认开启连接池(大小 5),可以通过create_engine的参数优化:

engine = create_engine( 'mysql+pymysql://root:root123@localhost:3306/test_db', pool_size=10, # 连接池大小(默认5) max_overflow=20, # 超出连接池后的最大连接数(默认10) pool_timeout=30, # 获取连接的超时时间(默认30秒) pool_recycle=1800 # 连接的存活时间(1800秒=30分钟,避免连接失效) ) 

2. 避免 SQL 注入(安全第一)

SQLAlchemy 的queryexecute方法会自动处理 SQL 注入(用参数化查询),禁止手动拼接 SQL

错误示例(会被 SQL 注入):

name = "张三'; DROP TABLE users; --" session.execute(f"SELECT * FROM users WHERE name='{name}'") # 危险! 

正确示例(参数化查询):

from sqlalchemy import text name = "张三'; DROP TABLE users; --" # 用text()和参数化查询 stmt = text("SELECT * FROM users WHERE name=:name") session.execute(stmt, {"name": name}) # 安全! 

3. 事务处理(避免数据不一致)

SQLAlchemy 的 Session 默认开启事务,必须 commit () 才会提交,rollback () 可以回滚:

try: user = User(name='王五', email='[email protected]') session.add(user) # 模拟错误(比如除以0) 1 / 0 session.commit() # 错误发生,不会执行 except Exception as e: session.rollback() # 回滚事务(取消之前的操作) print(f"错误:{e}") 

七、常见问题解答(小白踩坑高频区)

1. 连接报错 “Access denied for user 'root'@'localhost'”

  • 原因:密码错误或用户没有权限;

解决:检查连接字符串中的密码,或在 MySQL 中给 root 用户授权:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root123' WITH GRANT OPTION; FLUSH PRIVILEGES; 

2. 新增数据时报 “Duplicate entry '[email protected]' for key 'email'”

  • 原因:邮箱重复(unique=True约束);
  • 解决:确保插入的邮箱唯一,或在代码中处理重复错误。

3. 查询结果为空,但数据库中有数据

  • 原因:index=True需要先创建索引(或模型类的__tablename__写错);
  • 解决:检查模型类的__tablename__是否和数据库表名一致,或重新创建表(Base.metadata.drop_all()Base.metadata.create_all())。

八、总结:SQLAlchemy 的优势与适用场景

SQLAlchemy 是Python 中最强大的 ORM 框架,它的优势是:

  • 跨数据库支持:支持 MySQL、PostgreSQL、SQLite 等,切换数据库只需修改连接字符串;
  • 强大的查询 API:支持复杂查询(联表、分组、排序),不用写 SQL;
  • 事务管理:自动处理事务,避免数据不一致;
  • 性能优化:连接池、索引、延迟加载等功能提升性能。

适用场景

  • 中大型项目(需要复杂的数据库操作);
  • 多数据库切换(比如从 SQLite 迁移到 MySQL);
  • 需要事务管理和安全的项目(比如电商、金融)。

九、后续学习建议

  • 学习Alembic:数据库迁移工具(修改模型类后,自动更新表结构);
  • 学习SQLAlchemy Core:直接写 SQL 表达式(比 ORM 更灵活);
  • 学习查询优化:比如joinedload(预加载关联数据,避免 N+1 查询)。

最后,送你一句我用 SQLAlchemy 的经验:“ORM 是工具,不是银弹”—— 简单的查询可以用 ORM,复杂的查询(比如多表联查、统计)建议用 SQLAlchemy Core 或原生 SQL,平衡开发效率和性能。

Read more

RPA零基础入门:30分钟搭建第一个机器人

快速体验 1. 打开 InsCode(快马)平台 https://www.inscode.net 2. 输入框内输入如下内容: 设计一个面向新手的RPA教学项目,要求:1. 实现一个简单的文件整理机器人(自动分类下载文件夹中的文件)2. 包含分步骤教程和注释 3. 提供可视化流程图 4. 设置常见问题解答 5. 包含扩展练习建议。使用UiPath或Automation Anywhere社区版,确保代码简单易懂,适合零基础用户。 1. 点击'项目生成'按钮,等待项目生成完整后预览效果 今天想和大家分享一个特别适合RPA新手的实战项目——用30分钟搭建一个能自动整理文件的机器人。这个项目不需要编程基础,只要跟着步骤操作,就能快速感受到自动化带来的效率提升。 1. RPA是什么?为什么值得学? RPA全称机器人流程自动化,就像雇了个数字员工帮你处理重复性工作。比如自动填表、整理文件、收发邮件等。我最初接触时也很疑惑:

By Ne0inhk

Face Fusion能否集成Stable Diffusion?创意组合玩法

Face Fusion能否集成Stable Diffusion?创意组合玩法深度解析 1. 引言:当人脸融合遇上AI绘画 你有没有想过,如果能把一张照片里的人脸,完美地“移植”到另一张由AI生成的奇幻场景里,会是什么效果?比如,把自己的脸放到一幅赛博朋克风格的未来城市画作中,或者让历史人物“穿越”到现代艺术里。 这正是我们今天要探讨的核心问题:Face Fusion(人脸融合)技术,能否与Stable Diffusion这样的AI绘画模型结合,创造出前所未有的创意玩法? Face Fusion,简单来说,就是能把一张图片(源图像)里的人脸特征,智能地融合到另一张图片(目标图像)上。而Stable Diffusion,则是目前最强大的文生图AI模型之一,能根据文字描述生成各种风格的图像。这两者看似独立,但如果能结合起来,就能打开一扇通往无限创意的大门。 本文将带你深入探索这种技术组合的可能性。我们将从Face Fusion的基本原理讲起,分析它与Stable Diffusion集成的技术路径,并分享一些极具想象力的创意玩法。无论你是AI技术爱好者、内容创作者,

By Ne0inhk
【花雕动手做】拆解机器人底盘DDSM400钕强磁外转子65mm伺服轮毂电机

【花雕动手做】拆解机器人底盘DDSM400钕强磁外转子65mm伺服轮毂电机

做小型高精度全向机器人底盘,想找一款 “省心又能打” 的动力核心?DDSM400 钕强磁外转子 65mm 伺服轮毂电机 绝对是优选——它把无刷电机、FOC 伺服驱动、高精度编码器集成一体,钕强磁加持、外转子直驱设计,不用额外搭配驱动板,直接装轮就能用,是麦克纳姆轮底盘的 “一体化动力神器”。 但很多创客只知道它好用,却不清楚内部构造:钕强磁转子藏着怎样的动力秘密?伺服驱动和编码器是如何实现精准控制的?外转子直驱为什么能做到零背隙、低噪音? 这里,就完整拆解这款 DDSM400 伺服轮毂电机,从外到内拆解核心部件,解析它的结构优势与工作逻辑,帮你真正看懂这款 “一体化伺服电机”,以后选型、改装、调试机器人底盘,都能心里有底、少走弯路。 DDSM400 伺服轮毂电机・简单拆解步骤 1、拧下轮毂固定螺丝用内六角扳手卸下电机外圈的固定螺丝,分离轮毂外壳与端盖。 2、取出外转子与强磁体轻轻取下外转子总成,内部可见一圈钕铁硼强磁,注意磁力较大,轻拿轻放。 3、

By Ne0inhk

一、FPGA到底是什么???(一篇文章让你明明白白)

一句话概括 FPGA(现场可编程门阵列) 是一块可以通过编程来“变成”特定功能数字电路的芯片。它不像CPU或GPU那样有固定的硬件结构,而是可以根据你的需求,被配置成处理器、通信接口、控制器,甚至是整个片上系统。 一个生动的比喻:乐高积木 vs. 成品玩具 * CPU(中央处理器):就像一个工厂里生产好的玩具机器人。它的功能是固定的,你只能通过软件(比如按不同的按钮)来指挥它做预设好的动作(走路、跳舞),但你无法改变它的机械结构。 * ASIC(专用集成电路):就像一个为某个特定任务(比如只会翻跟头)而专门设计和铸造的金属模型。性能极好,成本低(量产时),但一旦制造出来,功能就永远无法改变。 * FPGA:就像一盒万能乐高积木。它提供了大量基本的逻辑单元(逻辑门、触发器)、连线和接口模块。你可以通过“编程”(相当于按照图纸搭建乐高)将这些基本模块连接起来,构建出你想要的任何数字系统——可以今天搭成一个CPU,明天拆了重新搭成一个音乐播放器。 “现场可编程”

By Ne0inhk