Flask SQLAlchemy 一对多与多对多查询详解
本文详细解析 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 查询功能的全部内容,希望对读者的学习有所帮助,欢迎继续支持本站获取更多技术资源。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













