1. Flask与SQLAlchemy的黄金组合
(开场白)第一次用Flask连接数据库时,我对着满屏的SQL语句发呆——直到遇见SQLAlchemy。这个Python界的ORM神器,让数据库操作变得像操作普通Python对象一样自然。今天我们就来深度剖析这对黄金搭档的实战用法,从基础配置到高级查询技巧,全是项目里摸爬滚打总结出的干货。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与基础配置
2.1 安装与初始化
在虚拟环境中执行这两条命令:
bash复制pip install flask-sqlalchemy
pip install pymysql # 以MySQL为例
初始化配置写在Flask应用工厂中:
python复制from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:pass@localhost/dbname'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
关键细节:TRACK_MODIFICATIONS关闭可避免性能损耗,生产环境必配
2.2 模型定义规范
用户模型的经典写法:
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)
def __repr__(self):
return f'<User {self.username}>'
字段类型选择技巧:
- 字符串用String(length)而非Text(除非超255字符)
- 金额用Numeric(10,2)避免浮点误差
- 时间戳用DateTime而非字符串
3. 数据库操作全指南
3.1 增删改查基础版
python复制# 增
new_user = User(username='alice', email='alice@example.com')
db.session.add(new_user)
db.session.commit()
# 查
user = User.query.filter_by(username='alice').first()
# 改
user.email = 'new_email@example.com'
db.session.commit()
# 删
db.session.delete(user)
db.session.commit()
3.2 高级查询技巧
多条件查询:
python复制from sqlalchemy import and_, or_
User.query.filter(
or_(
User.username.startswith('a'),
and_(User.email.contains('example'), User.id > 10)
)
).all()
分页查询优化方案:
python复制page = request.args.get('page', 1, type=int)
per_page = 20
users = User.query.order_by(User.id.desc()).paginate(page=page, per_page=per_page)
4. 关系型数据处理
4.1 一对多关系
文章和评论的典型关系:
python复制class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
comments = db.relationship('Comment', backref='article', lazy='dynamic')
class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
article_id = db.Column(db.Integer, db.ForeignKey('article.id'))
注意:lazy='dynamic'适合大型数据集,避免立即加载全部关联对象
4.2 多对多关系
用户和角色的关联表模式:
python复制roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('role_id', db.Integer, db.ForeignKey('role.id'))
)
class User(db.Model):
roles = db.relationship('Role', secondary=roles_users, backref='users')
5. 性能优化实战
5.1 批量操作
替代循环插入的高效写法:
python复制db.session.bulk_insert_mappings(User, [
{'username': 'user1', 'email': 'user1@test.com'},
{'username': 'user2', 'email': 'user2@test.com'}
])
5.2 连接池配置
生产环境必备设置:
python复制app.config['SQLALCHEMY_POOL_SIZE'] = 20
app.config['SQLALCHEMY_POOL_RECYCLE'] = 300
app.config['SQLALCHEMY_POOL_TIMEOUT'] = 10
6. 常见坑点解决方案
6.1 事务超时处理
python复制try:
db.session.execute('SET SESSION wait_timeout=28800')
# 长时间事务操作...
except Exception as e:
db.session.rollback()
raise e
6.2 连接泄露检测
在请求结束时自动回收连接:
python复制@app.teardown_appcontext
def shutdown_session(exception=None):
db.session.remove()
7. 与前端交互实践
7.1 JSON序列化方案
模型添加to_dict方法:
python复制def to_dict(self):
return {
'id': self.id,
'username': self.username,
'_links': {
'self': url_for('api.get_user', id=self.id)
}
}
7.2 分页数据格式
统一API响应结构:
python复制{
"items": [user.to_dict() for user in users.items],
"meta": {
"page": users.page,
"per_page": users.per_page,
"total_pages": users.pages,
"total_items": users.total
}
}
(实战心得)在最近一个日活10万+的项目中,我们通过调整SQLALCHEMY_ENGINE_OPTIONS中的pool_pre_ping=True参数,解决了凌晨数据库维护后连接失效的问题。这种实战经验才是团队最宝贵的知识资产。
