1. 使用Flask-SQLAlchemy
SQLAlchemy是一个强大的ORM(对象关系映射)库,通过Python对象与数据库表进行交互,无需编写SQL语句。Flask-SQLAlchemy是Flask的官方扩展,集成了SQLAlchemy。
安装Flask-SQLAlchemy
pip install flask-sqlalchemy
配置SQLAlchemy
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # SQLite数据库(开发环境推荐) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app)
2. 定义模型
模型是数据库表的Python类,每个模型类代表数据库中的一张表。
class User(db.Model): 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) age = db.Column(db.Integer, nullable=True) def __repr__(self): return f'<User {self.username}>'
常用字段类型
| 字段类型 | 说明 | Python类型 |
|---|---|---|
db.Integer |
整数 | int |
db.String(n) |
可变长度字符串 | str |
db.Text |
长文本 | str |
db.Boolean |
布尔值 | bool |
db.DateTime |
日期时间 | datetime.datetime |
db.Date |
日期 | datetime.date |
db.Float |
浮点数 | float |
db.Decimal |
高精度小数 | decimal.Decimal |
db.JSON |
JSON数据 | dict / list |
常用字段参数
| 参数 | 说明 |
|---|---|
primary_key=True |
主键 |
unique=True |
值唯一 |
nullable=False |
不允许为空 |
default=value |
默认值 |
index=True |
创建索引 |
autoincrement=True |
自增(整数主键默认) |
3. 创建和管理数据库
在定义了模型后,需要在应用上下文中创建数据库和表:
with app.app_context(): db.create_all() # 创建所有模型对应的表
删除所有表(谨慎使用)
with app.app_context(): db.drop_all() # 删除所有表,数据会丢失
4. CRUD操作
创建记录(Create)
@app.route('/add_user') def add_user(): new_user = User(username='john_doe', email='john@example.com', age=25) db.session.add(new_user) # 添加到会话 db.session.commit() # 提交事务,保存到数据库 return 'User added!' # 批量添加 @app.route('/add_users') def add_users(): users = [ User(username='alice', email='alice@example.com'), User(username='bob', email='bob@example.com'), ] db.session.add_all(users) db.session.commit() return 'Users added!'
读取记录(Read)
# 查询所有记录 @app.route('/get_users') def get_users(): users = User.query.all() return '<br>'.join([f'{user.username} ({user.email})' for user in users]) # 通过主键查询单个记录 user = User.query.get(1) # 查询id=1的用户 # 通过条件查询(精确匹配) user = User.query.filter_by(username='john_doe').first() # 通过条件查询(多个条件) users = User.query.filter_by(username='john_doe', age=25).all() # 获取第一条记录 user = User.query.first()
更新记录(Update)
@app.route('/update_user/<int:user_id>') def update_user(user_id): user = User.query.get(user_id) if user: user.username = 'new_username' user.age = 26 db.session.commit() return 'User updated!' return 'User not found!'
删除记录(Delete)
@app.route('/delete_user/<int:user_id>') def delete_user(user_id): user = User.query.get(user_id) if user: db.session.delete(user) db.session.commit() return 'User deleted!' return 'User not found!'
5. 高级查询操作
条件查询
from sqlalchemy import or_, and_, not_ # AND条件(默认) users = User.query.filter(User.username == 'john_doe', User.age > 18).all() # OR条件 users = User.query.filter( or_(User.username == 'john_doe', User.email == 'john@example.com') ).all() # AND显式 users = User.query.filter( and_(User.age >= 18, User.age <= 60) ).all() # NOT条件 users = User.query.filter(not_(User.username == 'admin')).all() # 模糊查询(LIKE) users = User.query.filter(User.username.like('%john%')).all() # 包含查询(IN) users = User.query.filter(User.username.in_(['alice', 'bob'])).all() # 为空判断 users = User.query.filter(User.email.is_(None)).all()
排序与分页
# 升序 users = User.query.order_by(User.username).all() # 降序 users = User.query.order_by(User.username.desc()).all() # 多字段排序 users = User.query.order_by(User.age.desc(), User.username).all() # 分页查询(每页10条,第1页) page = User.query.paginate(page=1, per_page=10) users = page.items # 当前页的数据 total = page.total # 总记录数 pages = page.pages # 总页数 has_prev = page.has_prev # 是否有上一页 has_next = page.has_next # 是否有下一页
聚合查询
from sqlalchemy import func # 计数 count = User.query.count() # 求和 total_age = db.session.query(func.sum(User.age)).scalar() # 平均值 avg_age = db.session.query(func.avg(User.age)).scalar() # 最大值/最小值 max_age = db.session.query(func.max(User.age)).scalar() min_age = db.session.query(func.min(User.age)).scalar()
6. 使用Flask-Migrate进行数据库迁移
当模型发生变化时(如新增字段),Flask-Migrate可以生成迁移脚本,自动更新表结构而不丢失数据。
安装Flask-Migrate
pip install flask-migrate
配置Flask-Migrate
from flask_migrate import Migrate migrate = Migrate(app, db)
迁移命令
# 1. 初始化迁移环境(只需执行一次) flask db init # 2. 生成迁移脚本(检测模型变化) flask db migrate -m "添加age字段" # 3. 应用迁移到数据库 flask db upgrade # 4. 回滚到上一个版本 flask db downgrade
| 命令 | 作用 |
|---|---|
flask db init |
初始化迁移环境,生成migrations/目录 |
flask db migrate -m "描述" |
生成迁移脚本(不修改数据库) |
flask db upgrade |
应用迁移,更新数据库结构 |
flask db downgrade |
回滚到上一个迁移版本 |
7. 执行原始SQL
虽然SQLAlchemy提供了强大的ORM功能,但在某些复杂场景下可能需要执行原始SQL语句。
# 查询 @app.route('/raw_sql') def raw_sql(): result = db.session.execute('SELECT * FROM user') return '<br>'.join([str(row) for row in result]) # 带参数的查询(防止SQL注入) @app.route('/user/<int:user_id>') def get_user_raw(user_id): result = db.session.execute( 'SELECT * FROM user WHERE id = :id', {'id': user_id} ) user = result.fetchone() return f'User: {user.username}' if user else 'Not found'
8. 连接MySQL数据库
除了SQLite,Flask-SQLAlchemy也支持MySQL、PostgreSQL等主流数据库。
安装MySQL驱动
# 选择一种安装 pip install mysqlclient # 推荐,性能好 # 或 pip install pymysql # 纯Python实现
配置MySQL连接
# URI格式: mysql://用户名:密码@主机:端口/数据库名 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost:3306/dbname' # 如需指定字符集 # app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/dbname?charset=utf8mb4'
完整示例
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@localhost/mydb' 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, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) @app.route('/') def index(): users = User.query.all() return '<br>'.join([f'{user.username} ({user.email})' for user in users]) if __name__ == '__main__': with app.app_context(): db.create_all() app.run(debug=True)
9. 常用数据库URI格式
| 数据库 | URI格式 |
|---|---|
| SQLite | sqlite:///path/to/database.db |
| SQLite(内存) | sqlite:///:memory: |
| MySQL | mysql://username:password@host/dbname |
| PostgreSQL | postgresql://username:password@host/dbname |
| MariaDB | mariadb://username:password@host/dbname |
10. CRUD操作速查表
| 操作 | 代码 |
|---|---|
| 创建记录 | db.session.add(obj); db.session.commit() |
| 批量创建 | db.session.add_all([obj1, obj2]); db.session.commit() |
| 查询所有 | Model.query.all() |
| 主键查询 | Model.query.get(id) |
| 条件查询(单条) | Model.query.filter_by(key=value).first() |
| 条件查询(多条) | Model.query.filter_by(key=value).all() |
| 复杂条件 | Model.query.filter(or_(...)).all() |
| 排序 | Model.query.order_by(Model.field.desc()).all() |
| 分页 | Model.query.paginate(page=1, per_page=10) |
| 更新 | obj.field = new_value; db.session.commit() |
| 删除 | db.session.delete(obj); db.session.commit() |
| 计数 | Model.query.count() |
小结
本章全面讲解了Flask的数据库操作。Flask-SQLAlchemy是推荐的ORM方案------通过定义继承自db.Model的模型类来映射数据库表,使用db.Column定义字段;CRUD操作通过db.session.add()创建、Model.query查询、直接修改属性后commit()更新、db.session.delete()删除;高级查询支持filter/filter_by条件过滤、or_/and_组合条件、order_by排序、paginate分页;Flask-Migrate管理数据库迁移;也支持执行原始SQL和连接MySQL等主流数据库。这些知识构成了Flask数据持久化的完整基础。