一对多。例如,班级与学生,一个班级对应多个学生,或者多个学生对应一个班级。sql
多对多。例如,学生与课程,能够有多个学生修同一门课,同时,一门课也有不少学生。数据库
若是一个项目,有两张表。分别是班级表,学生表。flask
在设计数据表时,咱们给学生表设置一个外键,指向班级表的 id 。session
sqlalchemy 模板建立表的代码:app
1 from flask import Flask, render_template, request, flash, redirect 2 from flask_sqlalchemy import SQLAlchemy 3 4 app = Flask(__name__,static_folder="static",template_folder="templates") 5 6 # 设置数据库链接属性 7 app.config['SQLALCHEMY_DATABASE_URI'] = '×××' 8 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 9 10 # 实例化 ORM 操做对象 11 db = SQLAlchemy(app) 12 13 # 班级表 14 class Classes(db.Model): 15 __tablename__ = "classes" 16 id = db.Column(db.Integer,primary_key=True) 17 name = db.Column(db.String(20),nullable=False,unique=True) 18 19 # 学生表 20 class Students(db.Model): 21 __tablename__ = "students" 22 id = db.Column(db.Integer,primary_key=True) 23 name = db.Column(db.String(40),nullable=False) 24 cls_id = db.Column(db.Integer,db.ForeignKey("classes.id")) # 注意要写成(表名.字段名)
建立完表,插入完数据后。测试
若是咱们知道学生的学号,要查学生班级的名称,应该怎么操做呢?spa
如今能够用一种比较麻烦的方达查询:设计
cls_id = Students.query.filter(Student.id == 'xxx').first() cls = Classes.query.filter(Classes.id == cls.id).first() print(cls.name)
这样的方法太麻烦了,有没有简单的办法?code
上面建立表的代码,在18行能够插入一条语句。orm
relate_student = db.relationship("Students",backref='relate_class',lazy='dynamic')
- 其中realtionship描述了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)