Flask 数据库操作(深入浅出)

Flask 数据库操作入门:从零开始构建数据驱动应用

在 Web 开发中,数据是应用的“血液”。无论是用户注册信息、文章内容,还是电商订单记录,都离不开数据库的支撑。对于使用 Flask 框架的开发者来说,掌握 Flask 数据库操作是迈向实战项目的必经之路。

Flask 本身不自带数据库功能,但它通过扩展机制完美支持多种数据库,其中最常用的是 SQLite 和 PostgreSQL。本文将带你从零开始,手把手实现完整的 Flask 数据库操作流程,包括模型定义、数据增删改查、关系管理,以及常见的最佳实践。


安装与环境准备

在开始之前,我们需要搭建基础开发环境。建议使用 Python 3.8 或更高版本。

打开终端,执行以下命令安装 Flask 和 SQLAlchemy:

pip install flask flask-sqlalchemy

这里我们使用 SQLAlchemy 作为 ORM(对象关系映射)工具。它就像一个“翻译官”,把 Python 对象转换成数据库中的表结构,又把数据库记录还原成 Python 对象。

💡 小贴士:ORM 的作用就像你写中文日记,但系统自动帮你翻译成英文存档。你不用关心 SQL 语句,只专注业务逻辑。

接下来创建项目文件结构:

flask_app/
├── app.py
└── instance/
    └── app.db

其中 app.py 是主程序文件,instance/app.db 是 SQLite 数据库文件(会自动生成)。


定义数据模型:让 Python 对象“活”起来

在 Flask 中,数据库操作的第一步是定义模型(Model)。模型就是数据库表的 Python 表示。

创建 app.py 并输入以下代码:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///instance/app.db'

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)   # 邮箱,唯一且不能为空
    created_at = db.Column(db.DateTime, default=db.func.now())       # 创建时间,默认为当前时间

    # 可选:定义字符串表示,方便调试
    def __repr__(self):
        return f'<User {self.username}>'

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)   # 文章标题
    content = db.Column(db.Text, nullable=False)        # 文章内容
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)  # 外键,关联用户
    created_at = db.Column(db.DateTime, default=db.func.now())

    # 关联 User 模型,用于反向查询
    author = db.relationship('User', backref=db.backref('posts', lazy=True))

    def __repr__(self):
        return f'<Post {self.title}>'

✅ 注释说明:

  • db.Column 定义字段,db.Integer 表示整数类型,db.String(80) 表示最多 80 个字符的字符串。
  • primary_key=True 表示该字段为主键。
  • unique=True 确保字段值唯一,如用户名不能重复。
  • nullable=False 表示该字段不能为空。
  • db.ForeignKey('user.id') 建立外键关系,实现一对多关联。
  • backref 定义反向关系,例如 user.posts 可以获取该用户的所有文章。

创建数据库表:让模型“落地”

模型定义完成后,需要在数据库中真正创建对应的表。

app.py 的最后添加以下代码:

with app.app_context():
    db.create_all()

print("数据库表已创建完成!")

🔧 注意:app.app_context() 是必须的,因为 Flask 的数据库操作必须在应用上下文中执行。

运行 python app.py,你会看到控制台输出:

数据库表已创建完成!

此时,instance/app.db 文件中已经生成了 userpost 两张表。

你可以用 SQLite 浏览器(如 DB Browser for SQLite)打开该文件查看结构,验证是否成功。


数据增删改查:Flask 数据库操作的核心

现在我们来实现完整的数据操作功能。

插入数据:新增用户与文章

with app.app_context():
    # 创建新用户
    new_user = User(username='alice', email='alice@example.com')
    db.session.add(new_user)           # 添加到会话
    db.session.commit()                # 提交事务,保存到数据库

    # 创建文章并关联用户
    new_post = Post(title='我的第一篇文章', content='这是我的第一篇 Flask 文章。', user_id=new_user.id)
    db.session.add(new_post)
    db.session.commit()

    print("用户和文章已成功插入!")

📌 关键点:

  • db.session.add() 将对象加入“待操作队列”。
  • db.session.commit() 执行事务,真正写入数据库。
  • 未提交前,数据不会持久化。

查询数据:从数据库中“捞”数据

with app.app_context():
    users = User.query.all()  # 查询所有用户
    print("所有用户:")
    for user in users:
        print(f"ID: {user.id}, 用户名: {user.username}, 邮箱: {user.email}")

    # 查询特定用户
    alice = User.query.filter_by(username='alice').first()
    if alice:
        print(f"\n找到用户:{alice.username}")
        print(f"创建时间:{alice.created_at}")

    # 查询某用户的全部文章
    posts = Post.query.filter_by(user_id=alice.id).all()
    print(f"\n{alice.username} 的文章数量:{len(posts)}")
    for post in posts:
        print(f"- {post.title}")

📊 小比喻:User.query 就像在图书馆找书,filter_by 是筛选条件,first() 是“第一个匹配的书”。

更新数据:修改已有记录

with app.app_context():
    # 找到用户并修改
    user = User.query.filter_by(username='alice').first()
    if user:
        user.email = 'alice_new@example.com'
        db.session.commit()
        print(f"用户 {user.username} 的邮箱已更新为 {user.email}")

✅ 无需 add(),直接修改对象属性,commit() 会自动识别变更。

删除数据:移除不再需要的信息

with app.app_context():
    user = User.query.filter_by(username='alice').first()
    if user:
        db.session.delete(user)      # 标记删除
        db.session.commit()
        print(f"用户 {user.username} 已被删除")

⚠️ 注意:删除操作需要 commit() 才生效,否则只是“标记”。


关系管理:一对多与反向查询

前面我们定义了 UserPost 的一对多关系。现在我们深入理解它的用法。

with app.app_context():
    user = User.query.filter_by(username='alice').first()
    if user:
        # 通过 user.posts 获取该用户的所有文章
        for post in user.posts:
            print(f"文章标题:{post.title}")

🔄 这就是 backref 的威力:User 拥有 posts 属性,而 Post 拥有 author 属性,双向导航。


高级技巧:事务与错误处理

在实际项目中,多个操作需要“原子性”——要么全部成功,要么全部失败。

with app.app_context():
    try:
        # 开始事务
        user = User(username='bob', email='bob@example.com')
        db.session.add(user)
        
        post = Post(title='学习 Flask', content='很有趣!', user_id=user.id)
        db.session.add(post)

        db.session.commit()  # 成功则提交
        print("用户和文章添加成功!")

    except Exception as e:
        db.session.rollback()  # 出错则回滚
        print(f"操作失败,已回滚:{e}")

🛡️ rollback() 保证了数据一致性,避免部分写入导致脏数据。


总结:Flask 数据库操作的完整闭环

本文系统讲解了 Flask 数据库操作的核心流程:从环境搭建、模型定义、表创建,到增删改查和关系管理,再到事务处理。整个过程逻辑清晰、层层递进。

Flask 数据库操作的本质,是通过 ORM 将 Python 代码与数据库表进行“映射”,让你用面向对象的方式操作数据,而无需编写复杂的 SQL 语句。

无论你是初学者还是中级开发者,掌握这些技能后,你都可以轻松构建出支持用户注册、文章发布、数据管理等功能的完整 Web 应用。

记住:数据库是应用的基石,扎实的 Flask 数据库操作能力,是你走向高级开发的重要一步。