Flask操作MySQL用什么库好?flask-sqlalchemy与pymysql深度解析

来源:SpringBoot教程作者:广州网站建设头衔:草根站长
导读:本期聚焦于广州网站建设创作的《Flask操作MySQL用什么库好?flask-sqlalchemy与pymysql深度解析》,敬请观看详情。为什么同样是Flask连接MySQL,有人用pymysql直连,有人却坚持用SQLAlchemy?这两条路线在开发效率、性能和维护成本上差别不小。本文从连接配置入手,讲解Flask中操作MySQL的主流方案,包括flask-sqlalchemy的模型定义、增删改查写法、连接池配置,以及pymysql原生操作和常见坑点,还会对比两种方式的适用场景,帮你根据项目规模选出合适的数据库访问层方案,并附上可直接运行的完整代码示例。

在Flask生态里操作MySQL,最常见的问题就是该选哪种方式。有人直接用pymysql写原生SQL,觉得简单可控;有人用flask-sqlalchemy做ORM,开发速度快但心里没底。这两种方案没有绝对的好坏,关键在于理解它们各自的工作机制和适用边界。本文会把两条路线的配置、写法、坑点都梳理一遍,帮你做出合适的选择。

Flask操作MySQL用什么库好?flask-sqlalchemy与pymysql深度解析

一、先搞清楚Flask连接MySQL的依赖关系

Flask本身是一个轻量Web框架,它不内置数据库支持,需要自己组合依赖。如果用ORM方式,通常需要两个包:SQLAlchemy负责数据库抽象层,flask-sqlalchemy负责把SQLAlchemy和Flask的应用上下文整合起来,PyMySQL则是Python与MySQL通信的驱动。也就是说,即便你用的是ORM,底层真正建立TCP连接、传输SQL语句的仍然是PyMySQL这类驱动。

安装方式如下:

pip install flask flask-sqlalchemy pymysql

这里有个新手常踩的坑:如果只装了SQLAlchemy而没装PyMySQL,连接MySQL时会报ModuleNotFoundError或者Can't load plugin之类的错误。另外MySQL 8.0默认使用caching_sha2_password认证方式,老版本驱动可能连不上,PyMySQL在较新版本中已经支持,遇到问题可以先升级驱动再排查其他原因。

连接字符串的写法也值得注意,正确格式是mysql+pymysql://用户名:密码@主机:3306/数据库名?charset=utf8mb4。前半段的mysql+pymysql告诉SQLAlchemy使用PyMySQL作为DBAPI,冒号和@符号如果出现在密码里,必须做URL编码,否则解析会出错,这也是很多人配置看起来没问题却连不上的原因。

二、flask-sqlalchemy的模型定义与增删改查

flask-sqlalchemy是Flask官方推荐的ORM整合方案,它的核心价值在于把数据库表映射成Python类,让你用操作对象的方式操作数据。先看一个完整的最小示例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 配置数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/test?charset=utf8mb4'
# 关闭对模型修改的追踪,节省内存
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), nullable=False)
    email = db.Column(db.String(100), unique=True)

    def to_dict(self):
        return {'id': self.id, 'name': self.name, 'email': self.email}

@app.route('/users')
def list_users():
    users = User.query.all()
    return {'data': [u.to_dict() for u in users]}

if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 根据模型自动建表
    app.run(debug=True)

增删改查的基本写法如下。插入数据要经历三步:db.session.add()把对象放入会话,db.session.commit()真正提交事务,出错时用db.session.rollback()回滚。这个session不是浏览器的session,它是SQLAlchemy的工作单元,负责追踪对象变化并把它翻译成SQL。

# 插入
user = User(name='张三', email='zhangsan@ipipp.com')
db.session.add(user)
db.session.commit()

# 查询
user = User.query.filter_by(name='张三').first()
total = User.query.count()

# 更新
user.email = 'new@ipipp.com'
db.session.commit()

# 删除
db.session.delete(user)
db.session.commit()

需要注意flask-sqlalchemy 3.x和2.x的API有差异,3.x更推荐用db.session.execute(db.select(User))替代旧的User.query风格,旧写法虽然还能用,但新项目建议跟进新API,避免日后升级踩坑。

三、PyMySQL原生操作:更轻但责任更大

如果你觉得ORM太重,直接用PyMySQL也完全可行。它的优点是SQL完全由你掌控,执行路径清晰,排查问题直观;缺点是手写SQL容易拼错、需要自己管理连接和事务、没有对象映射能力。一个典型的写法是封装一个数据库工具类:

import pymysql
from flask import current_app

def get_conn():
    return pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456',
        database='test',
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor  # 查询结果返回字典
    )

def query_users(name):
    conn = get_conn()
    try:
        with conn.cursor() as cursor:
            sql = 'SELECT id, name, email FROM users WHERE name = %s'
            cursor.execute(sql, (name,))  # 参数化查询,防止SQL注入
            return cursor.fetchall()
    finally:
        conn.close()

def add_user(name, email):
    conn = get_conn()
    try:
        with conn.cursor() as cursor:
            sql = 'INSERT INTO users (name, email) VALUES (%s, %s)'
            cursor.execute(sql, (name, email))
        conn.commit()
    except Exception:
        conn.rollback()
        raise
    finally:
        conn.close()

这里有三点必须强调。第一,永远不要用字符串拼接构造SQL,%s占位符配合参数传递是防止SQL注入的底线,任何把用户输入直接拼进SQL的做法都是安全隐患。第二,原生的conn.cursor()默认返回元组,加上DictCursor后返回字典,取字段会方便很多。第三,每次请求都新建连接开销不小,小型项目无所谓,并发上来后应该引入连接池,比如用DBUtilsPooledDB,或者干脆回到SQLAlchemy,它自带连接池管理。

四、两种方案怎么选:从项目规模和团队能力出发

选型的判断依据其实很实际。如果你在做中大型项目、表结构会随业务演化、团队成员水平参差不齐,flask-sqlalchemy的价值会越来越明显:模型即文档、自动处理事务、防止注入、迁移工具Alembic配合管理表结构变更,这些能力在长期维护中省下的时间远超学习成本。

反之,如果项目很小、查询高度定制化(复杂报表、大量多表关联统计)、或者团队对SQL非常熟,原生PyMySQL反而更直接。还有一种折中做法:整体用ORM,个别性能敏感的查询用db.session.execute()执行原生SQL,两种方式共存并不冲突:

from sqlalchemy import text

# 在ORM项目中执行原生SQL
rows = db.session.execute(
    text('SELECT name, COUNT(*) AS cnt FROM users GROUP BY name HAVING cnt > :n'),
    {'n': 5}
).fetchall()

最后提醒两个通用配置点。一是连接池参数,SQLAlchemy可通过SQLALCHEMY_ENGINE_OPTIONS设置pool_sizepool_recycle,后者建议设为3600左右,避免连接被MySQL的wait_timeout掐断后报MySQL server has gone away。二是字符集统一用utf8mb4,如果只在连接串里设置而建表时用了utf8,遇到emoji或生僻字依然会报错。把这些细节提前处理好,数据库层就不会成为项目的短板。

Flask MySQLflask-sqlalchemypymysql修改时间:2026-09-15 14:24:42

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260915/57326.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。