1. 项目概述
在Web开发中,数据库操作是最基础也是最重要的环节之一。作为Python轻量级框架的Flask,与MySQL数据库的结合使用非常普遍。本文将详细介绍如何在Flask项目中连接MySQL数据库,并使用ORM(对象关系映射)技术实现基本的增删改查操作。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备
2.1 安装必要依赖
首先需要安装Flask和MySQL相关的Python包:
bash复制pip install flask flask-sqlalchemy pymysql
这里我们选择flask-sqlalchemy作为ORM工具,pymysql作为MySQL的Python驱动。
提示:生产环境中建议使用
mysqlclient替代pymysql,性能更好。但pymysql安装更简单,适合开发环境。
2.2 MySQL数据库配置
确保本地或远程有可用的MySQL服务。如果还没有安装MySQL,可以从官网下载社区版安装。
创建测试数据库:
sql复制CREATE DATABASE flask_demo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3. Flask连接MySQL配置
3.1 基本配置
在Flask应用中配置数据库连接:
python复制from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password@localhost:3306/flask_demo'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
配置说明:
SQLALCHEMY_DATABASE_URI: 数据库连接字符串,格式为mysql+pymysql://用户名:密码@主机:端口/数据库名SQLALCHEMY_TRACK_MODIFICATIONS: 设为False以避免警告信息
3.2 连接池配置
对于生产环境,建议配置连接池:
python复制app.config['SQLALCHEMY_POOL_SIZE'] = 5
app.config['SQLALCHEMY_POOL_TIMEOUT'] = 30
app.config['SQLALCHEMY_POOL_RECYCLE'] = 3600
4. 定义数据模型
4.1 创建基础模型
我们先创建一个用户模型作为示例:
python复制class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
created_at = db.Column(db.DateTime, default=db.func.current_timestamp())
def __repr__(self):
return f'<User {self.username}>'
4.2 模型字段类型
SQLAlchemy支持多种字段类型:
| Python类型 | MySQL类型 | 说明 |
|---|---|---|
| Integer | INT | 整数 |
| String | VARCHAR | 字符串 |
| Text | TEXT | 长文本 |
| Boolean | BOOLEAN | 布尔值 |
| DateTime | DATETIME | 日期时间 |
| Float | FLOAT | 浮点数 |
5. 数据库迁移
5.1 初始化数据库
首次使用时需要创建表:
python复制with app.app_context():
db.create_all()
5.2 使用Flask-Migrate
对于更复杂的迁移需求,可以使用Flask-Migrate:
bash复制pip install flask-migrate
初始化:
python复制from flask_migrate import Migrate
migrate = Migrate(app, db)
然后执行:
bash复制flask db init
flask db migrate -m "initial migration"
flask db upgrade
6. ORM增删改查操作
6.1 创建(Create)
添加新记录:
python复制new_user = User(username='john', email='john@example.com')
db.session.add(new_user)
db.session.commit()
批量添加:
python复制users = [
User(username='alice', email='alice@example.com'),
User(username='bob', email='bob@example.com')
]
db.session.add_all(users)
db.session.commit()
6.2 读取(Read)
基本查询:
python复制# 获取所有用户
users = User.query.all()
# 获取第一个用户
first_user = User.query.first()
# 按ID获取用户
user = User.query.get(1)
条件查询:
python复制# 精确匹配
user = User.query.filter_by(username='john').first()
# 复杂条件
users = User.query.filter(User.email.endswith('@example.com')).all()
6.3 更新(Update)
更新记录:
python复制user = User.query.get(1)
user.email = 'new_email@example.com'
db.session.commit()
批量更新:
python复制User.query.filter_by(username='john').update({'email': 'updated@example.com'})
db.session.commit()
6.4 删除(Delete)
删除记录:
python复制user = User.query.get(1)
db.session.delete(user)
db.session.commit()
批量删除:
python复制User.query.filter(User.username.in_(['john', 'alice'])).delete()
db.session.commit()
7. 高级查询技巧
7.1 分页查询
python复制page = request.args.get('page', 1, type=int)
per_page = 10
users = User.query.paginate(page=page, per_page=per_page)
7.2 排序
python复制# 升序
users = User.query.order_by(User.username).all()
# 降序
users = User.query.order_by(User.username.desc()).all()
7.3 聚合函数
python复制from sqlalchemy import func
# 计数
count = db.session.query(func.count(User.id)).scalar()
# 平均值
avg = db.session.query(func.avg(User.id)).scalar()
8. 事务处理
8.1 基本事务
python复制try:
user1 = User(username='user1', email='user1@example.com')
user2 = User(username='user2', email='user2@example.com')
db.session.add(user1)
db.session.add(user2)
db.session.commit()
except Exception as e:
db.session.rollback()
print(f"Error: {e}")
8.2 嵌套事务
python复制with db.session.begin_nested():
user = User(username='nested', email='nested@example.com')
db.session.add(user)
9. 性能优化
9.1 批量操作
使用bulk_insert_mappings提高插入性能:
python复制users = [
{'username': 'user3', 'email': 'user3@example.com'},
{'username': 'user4', 'email': 'user4@example.com'}
]
db.session.bulk_insert_mappings(User, users)
db.session.commit()
9.2 延迟加载
避免N+1查询问题:
python复制# 不好的做法
for user in User.query.all():
print(user.posts) # 每次循环都会查询数据库
# 好的做法 - 使用joinedload
from sqlalchemy.orm import joinedload
users = User.query.options(joinedload(User.posts)).all()
10. 常见问题与解决方案
10.1 连接超时
错误现象:
code复制OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query')
解决方案:
- 增加连接超时时间
- 配置连接池回收时间
10.2 编码问题
确保数据库、连接字符串和表都使用UTF-8编码:
python复制app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:pass@localhost/db?charset=utf8mb4'
10.3 性能慢查询
使用EXPLAIN分析慢查询:
python复制from sqlalchemy import text
result = db.session.execute(text('EXPLAIN SELECT * FROM users WHERE username LIKE "%a%"'))
for row in result:
print(row)
11. 最佳实践
- 始终使用ORM而不是原始SQL,除非有特殊性能需求
- 合理使用索引提高查询性能
- 生产环境使用连接池
- 定期备份数据库
- 使用迁移工具管理数据库变更
- 为常用查询添加缓存
12. 完整示例代码
python复制from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:password@localhost/flask_demo'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
@app.route('/users', methods=['GET'])
def get_users():
users = User.query.all()
return jsonify([{'id': u.id, 'username': u.username} for u in users])
@app.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = User.query.get_or_404(user_id)
return jsonify({'id': user.id, 'username': user.username})
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
在实际项目中,我发现ORM的使用能极大提高开发效率,但也需要注意避免常见的性能陷阱。特别是在处理复杂查询时,要时刻关注生成的SQL语句是否高效。另外,数据库连接的管理也很关键,不当的连接处理可能导致资源泄漏或性能问题。
