Flask SQLAlchemy 一对多与多对多查询详解

夏知夏
夏知夏
发布时间:2026-10-13 | 4人浏览过
原创

本文详细解析 Flask 中 SQLAlchemy ORM 框架的数据查询方法,重点讲解一对多(如班级与学生)和多对多(如学生与课程)关系的定义与查询。通过 relationship 函数配置关联属性,利用 backref 和 lazy 参数优化加载策略,并提供具体的代码示例展示如何高效获取关联数据。

本文深入解析 Flask 框架中 ORM 组件 SQLAlchemy 的查询机制,通过具体代码示例详细说明其应用方法,旨在为开发者的学习与实际工作提供具有参考价值的技术指南。

理解数据库关系类型

理解数据库中的关系类型:一对多与多对多。

所谓一对多关系,指的是一个实体对应多个其他实体。以班级和学生为例,一个班级可以包含多名学生,而多名学生则归属于同一个班级。

多对多关系则指两个实体之间相互对应多个对方。例如学生与课程的关系,一名学生可以选修多门课程,同时一门课程也可以被多名学生选修。

一对多关系查询实现

一对多关系的查询实现。

假设项目中存在两张数据表:班级表与学生表。

在数据库设计阶段,需为学生表添加外键字段,该外键指向班级表的主键 id,以此建立关联。

以下是使用 SQLAlchemy 模板创建数据表的代码实现。


from flask import Flask, render_template, request, flash, redirect
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__,static_folder="static",template_folder="templates")

# 设置数据库连接属性
app.config['SQLALCHEMY_DATABASE_URI'] = '×××'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 实例化 ORM 操作对象
db = SQLAlchemy(app)

# 班级表
class Classes(db.Model):
  __tablename__ = "classes"
  id = db.Column(db.Integer,primary_key=True)
  name = db.Column(db.String(20),nullable=False,unique=True)

# 学生表
class Students(db.Model):
  __tablename__ = "students"
  id = db.Column(db.Integer,primary_key=True)
  name = db.Column(db.String(40),nullable=False)
  cls_id = db.Column(db.Integer,db.ForeignKey("classes.id"))  # 注意要写成(表名.字段名)

完成数据表创建并插入初始数据后,即可进行查询操作。

若已知学生的学号,如何查询该学生所属班级的名称?以下是具体操作步骤。

可以采用一种较为繁琐的传统方式进行查询:


cls_id = Students.query.filter(Student.id == 'xxx').first()
cls = Classes.query.filter(Classes.id == cls.id).first()
print(cls.name)

上述方法代码冗余且不够简洁,是否存在更简便的查询方案?

在之前创建表的代码基础上,可以在第 18 行附近插入关联关系的定义语句。


relate_student = db.relationship("Students",backref='relate_class',lazy='dynamic')

其中,relationship 函数用于描述 Students 类与 Classes 类之间的关联。本例中,第一个参数指定了对应的参照类为 "Students"。

第二个参数 backref 用于在 Students 类中自动生成反向访问属性,方便从学生对象直接访问班级信息。

第三个参数 lazy 决定了 SQLAlchemy 从数据库加载关联数据的具体时机。

若设置为子查询方式(subquery),系统在加载 Classes 对象后会立即通过子查询加载关联对象,这能减少总查询次数,但若返回条目数量巨大,性能可能会下降。

此外,也可设置为动态方式(dynamic),此时关联对象仅在真正被使用时才进行加载,并在返回前进行过滤。如果返回的对象数量众多或未来可能激增,推荐采用此方式。若上述理论难以理解,掌握具体用法即可。

若已知学生姓名,想要查询其所属班级名称,可执行以下代码:


stu = Students.query.filter(Students.name == 'xxx').first()
stu.relate_class.name # stu.relate_class 会跳到 classes 表

若已知班级名称,想要获取该班级下所有学生姓名的列表,可执行以下代码:


cls = Classes.query.filter(Classes.name == 'xxx').first()
cls.relate_student.name # cls.relate_stu 会跳到 students 表

实现上述功能需满足两个条件:一是正确设置外键,二是添加特定的关系定义语句。


relate_student = db.relationship("Students",backref='relate_class',lazy='dynamic')

需注意区分 relate_student 与 relate_class 的使用场景,并准确书写 relationship 语句,确保逻辑清晰。

多对多关系查询实现

多对多关系的查询实现。

假设多名学生选修了不同的课程,这构成了典型的多对多关系模型。


tb_student_course = db.Table('tb_student_course',
               db.Column('student_id', db.Integer, db.ForeignKey('students.id')),
               db.Column('course_id', db.Integer, db.ForeignKey('courses.id'))
               )


class Student(db.Model):
  __tablename__ = "students"
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(64), unique=True)
   # 关联属性,多对多的情况,可以写在任意一个模型类中
  relate_courses = db.relationship('Course', secondary=tb_student_course,
               backref='relate_student',
               lazy='dynamic')

class Course(db.Model):
  __tablename__ = "courses"
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(64), unique=True)

首先添加测试数据以验证模型。


# 添加测试数据

  stu1 = Student(name='张三')
  stu2 = Student(name='李四')
  stu3 = Student(name='王五')

  cou1 = Course(name='物理')
  cou2 = Course(name='化学')
  cou3 = Course(name='生物')

  stu1.courses = [cou2, cou3]  # 记得要添加关系
  stu2.courses = [cou2]
  stu3.courses = [cou1, cou2, cou3]

  db.session.add_all([stu1, stu2, stu2])
  db.session.add_all([cou1, cou2, cou3])

  db.session.commit()

接下来演示如何查询某名学生选修的所有课程,以及选修了某门课程的所有学生名单。


for course in stu1.relate_courses:
  print(course.name)
for student in cou2.relate_student:
  print(student)

以上即为本文关于 Flask SQLAlchemy 查询功能的全部内容,希望对读者的学习有所帮助,欢迎继续支持本站获取更多技术资源。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表