Flask-SQLAlchemy全面指南:从模型定义到高级查询
一、初识Flask-SQLAlchemy
1.1 为什么选择ORM?
传统SQL操作存在以下痛点:
• SQL注入风险
• 不同数据库语法差异
• 重复编写CRUD代码
• 对象与关系数据转换繁琐
Flask-SQLAlchemy优势:
# 传统SQL操作
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
# ORM方式
user = User.query.get(user_id)
1.2 安装与配置
安装命令:
pip install flask-sqlalchemy pymysql
基础配置示例:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:password@localhost/dbname'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
配置参数说明:
• SQLALCHEMY_POOL_SIZE: 连接池默认大小(推荐5-10)
• SQLALCHEMY_ECHO: 开启SQL日志(调试模式)
• SQLALCHEMY_ENGINE_OPTIONS: 高级引擎配置
二、数据模型定义
2.1 学生模型示例
class Student(db.Model):
    """学生信息表"""
    __tablename__ = 'tb_student'
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False)
    sex = db.Column(db.Boolean, default=True, comment='性别')
    age = db.Column(db.SmallInteger, index=True)
    class_name = db.Column('class', db.String(10))
    description = db.Column(db.Text)
    status = db.Column(db.Boolean, default=True)
    created_at = db.Column(db.DateTime, default=datetime.now)
    def __repr__(self):
        return f'<Student {self.name}>'
字段类型对照表:
| ORM类型 | MySQL类型 | 说明 | 
|---|---|---|
| Integer | INT | 32位整数 | 
| String(20) | VARCHAR(20) | 可变长度字符串 | 
| Text | TEXT | 长文本数据 | 
| Boolean | TINYINT(1) | 布尔值存储 | 
| DateTime | DATETIME | 日期时间类型 | 
三、CRUD操作详解
3.1 创建数据
# 单条创建
new_student = Student(name='王小明', class_name='301', age=16)
db.session.add(new_student)
db.session.commit()
# 批量创建
students = [
    Student(name='张小红', class_name='302', age=17),
    Student(name='李小白', class_name='303', age=16)
]
db.session.bulk_save_objects(students)
db.session.commit()
3.2 查询操作
基础查询方法:
# 获取全部数据
all_students = Student.query.all()
# 获取第一条记录
first_student = Student.query.first()
# 主键查询
student = Student.query.get(1)
复杂条件查询:
from sqlalchemy import and_, or_
# 组合查询示例
result = Student.query.filter(
    or_(
        and_(Student.class_name == '301', Student.age >= 15),
        and_(Student.class_name == '302', Student.age < 18)
    )
).order_by(Student.created_at.desc()).limit(10).all()
3.3 更新数据
student = Student.query.get(1)
student.age = 17
db.session.commit()
# 批量更新
Student.query.filter_by(class_name='301').update({'age': Student.age + 1})
db.session.commit()
3.4 删除数据
student = Student.query.get(1)
db.session.delete(student)
db.session.commit()
四、高级查询技巧
4.1 分页查询
def paginate(page=1, per_page=20):
    return Student.query.order_by(Student.id).paginate(
        page=page, 
        per_page=per_page,
        error_out=False
    )
4.2 聚合查询
from sqlalchemy import func
# 统计班级人数
class_stats = db.session.query(
    Student.class_name,
    func.count(Student.id).label('total')
).group_by(Student.class_name).all()
4.3 关联查询
class Score(db.Model):
    student_id = db.Column(db.Integer, db.ForeignKey('tb_student.id'))
    # 定义关系
    student = db.relationship('Student', backref='scores')
# 关联查询示例
student_with_scores = db.session.query(Student, Score).join(
    Score, Student.id == Score.student_id
).filter(Student.class_name == '301').all()
五、原生SQL操作
5.1 执行原生查询
# 参数化查询防止SQL注入
sql = "SELECT * FROM tb_student WHERE class = :class_name"
result = db.session.execute(sql, {'class_name': '301'})
students = [dict(row) for row in result]
5.2 执行数据修改
update_sql = """
    UPDATE tb_student 
    SET age = age + 1 
    WHERE created_at < :threshold
"""
db.session.execute(update_sql, {'threshold': datetime(2023, 1, 1)})
db.session.commit()
六、最佳实践
6.1 性能优化
• 使用yield_per处理大数据集:
for student in Student.query.yield_per(100):
    process(student)
• 避免N+1查询问题:
# 使用joinedload进行关联加载
from sqlalchemy.orm import joinedload
students = Student.query.options(joinedload(Student.scores)).all()
6.2 安全建议
- 始终使用参数化查询
- 敏感字段加密存储
- 定期备份数据库
- 使用只读账号进行查询操作
6.3 错误处理
try:
    db.session.begin()
    # 数据库操作...
    db.session.commit()
except Exception as e:
    db.session.rollback()
    current_app.logger.error(f"Database error: {str(e)}")
    raise
七、扩展学习
- 
数据库迁移工具: pip install flask-migrate初始化: from flask_migrate import Migrate migrate = Migrate(app, db)
- 
查询性能分析: from sqlalchemy import event from sqlalchemy.engine import Engine @event.listens_for(Engine, "before_cursor_execute") def before_cursor_execute(conn, cursor, stmt, params, context, executemany): context._query_start_time = time.time() @event.listens_for(Engine, "after_cursor_execute") def after_cursor_execute(conn, cursor, stmt, params, context, executemany): duration = time.time() - context._query_start_time if duration > 0.5: # 记录慢查询 app.logger.warning(f"Slow query ({duration:.2f}s): {stmt}")
- 
异步支持(SQLAlchemy 2.0+): from sqlalchemy.ext.asyncio import create_async_engine async_engine = create_async_engine("mysql+asyncmy://user:pass@host/db")
通过本文的学习,您将掌握:
• Flask-SQLAlchemy的核心使用方法
• 复杂业务场景下的查询构建技巧
• 数据库操作的最佳实践
• 性能优化与安全防护策略
建议在实际项目中结合具体需求,灵活运用这些技术,并持续关注SQLAlchemy的版本更新和新特性。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号